adhearsion 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/CHANGELOG +11 -2
  2. data/EVENTS +1 -1
  3. data/Rakefile +4 -4
  4. data/adhearsion.gemspec +8 -4
  5. data/app_generators/ahn/USAGE +3 -3
  6. data/app_generators/ahn/ahn_generator.rb +11 -11
  7. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +3 -3
  8. data/app_generators/ahn/templates/components/disabled/restful_rpc/example-client.rb +6 -6
  9. data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.rb +16 -16
  10. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +42 -42
  11. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +11 -11
  12. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +1 -1
  13. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +6 -6
  14. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +4 -4
  15. data/app_generators/ahn/templates/config/startup.rb +31 -16
  16. data/bin/ahn +3 -3
  17. data/bin/ahnctl +8 -8
  18. data/bin/jahn +3 -3
  19. data/examples/asterisk_manager_interface/standalone.rb +2 -2
  20. data/lib/adhearsion.rb +4 -2
  21. data/lib/adhearsion/cli.rb +31 -31
  22. data/lib/adhearsion/component_manager.rb +39 -39
  23. data/lib/adhearsion/component_manager/component_tester.rb +14 -14
  24. data/lib/adhearsion/component_manager/spec_framework.rb +1 -1
  25. data/lib/adhearsion/events_support.rb +12 -12
  26. data/lib/adhearsion/foundation/blank_slate.rb +1 -1
  27. data/lib/adhearsion/foundation/custom_daemonizer.rb +2 -2
  28. data/lib/adhearsion/foundation/event_socket.rb +26 -26
  29. data/lib/adhearsion/foundation/future_resource.rb +6 -6
  30. data/lib/adhearsion/foundation/metaprogramming.rb +2 -2
  31. data/lib/adhearsion/foundation/numeric.rb +3 -3
  32. data/lib/adhearsion/foundation/relationship_properties.rb +7 -7
  33. data/lib/adhearsion/foundation/string.rb +8 -8
  34. data/lib/adhearsion/foundation/synchronized_hash.rb +8 -8
  35. data/lib/adhearsion/host_definitions.rb +16 -16
  36. data/lib/adhearsion/initializer.rb +74 -65
  37. data/lib/adhearsion/initializer/asterisk.rb +15 -9
  38. data/lib/adhearsion/initializer/configuration.rb +54 -39
  39. data/lib/adhearsion/initializer/database.rb +4 -4
  40. data/lib/adhearsion/initializer/drb.rb +6 -6
  41. data/lib/adhearsion/initializer/freeswitch.rb +1 -1
  42. data/lib/adhearsion/initializer/ldap.rb +51 -0
  43. data/lib/adhearsion/initializer/rails.rb +8 -8
  44. data/lib/adhearsion/logging.rb +16 -16
  45. data/lib/adhearsion/tasks/deprecations.rb +12 -12
  46. data/lib/adhearsion/tasks/generating.rb +2 -2
  47. data/lib/adhearsion/tasks/testing.rb +7 -7
  48. data/lib/adhearsion/version.rb +1 -1
  49. data/lib/adhearsion/voip/asterisk/agi_server.rb +44 -14
  50. data/lib/adhearsion/voip/asterisk/commands.rb +281 -237
  51. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +8 -8
  52. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +14 -14
  53. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +16 -16
  54. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +39 -39
  55. data/lib/adhearsion/voip/asterisk/config_manager.rb +13 -13
  56. data/lib/adhearsion/voip/asterisk/manager_interface.rb +91 -87
  57. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +739 -739
  58. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +60 -60
  59. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +16 -16
  60. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +1 -1
  61. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +13 -13
  62. data/lib/adhearsion/voip/asterisk/super_manager.rb +3 -3
  63. data/lib/adhearsion/voip/call.rb +101 -64
  64. data/lib/adhearsion/voip/call_routing.rb +9 -9
  65. data/lib/adhearsion/voip/constants.rb +7 -7
  66. data/lib/adhearsion/voip/conveniences.rb +1 -1
  67. data/lib/adhearsion/voip/dial_plan.rb +42 -40
  68. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +27 -27
  69. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +1 -1
  70. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +6 -6
  71. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +17 -17
  72. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +7 -7
  73. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +2 -2
  74. data/lib/adhearsion/voip/dsl/numerical_string.rb +3 -3
  75. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +7 -7
  76. data/lib/adhearsion/voip/freeswitch/event_handler.rb +1 -1
  77. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +20 -20
  78. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +5 -5
  79. data/lib/adhearsion/voip/freeswitch/oes_server.rb +33 -33
  80. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +1 -1
  81. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +2 -2
  82. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +9 -9
  83. data/lib/theatre.rb +18 -18
  84. data/lib/theatre/callback_definition_loader.rb +17 -17
  85. data/lib/theatre/guid.rb +6 -6
  86. data/lib/theatre/invocation.rb +19 -19
  87. data/lib/theatre/namespace_manager.rb +28 -28
  88. metadata +55 -14
@@ -54,7 +54,7 @@ module Adhearsion
54
54
  calculated_matches << calculated_match
55
55
  actual_potential_matches.concat calculated_match.potential_matches
56
56
  actual_exact_matches.concat calculated_match.exact_matches
57
-
57
+
58
58
  potential_matches << calculated_match if calculated_match.potential_match?
59
59
  exact_matches << calculated_match if calculated_match.exact_match?
60
60
  end
@@ -52,11 +52,11 @@ module Adhearsion
52
52
 
53
53
  def match(query)
54
54
  numerical_query = coerce_to_numeric query
55
- if numerical_query
55
+ if numerical_query
56
56
  exact_match = pattern.include?(numerical_query) ? query : nil
57
57
  potential_matches = numbers_in_range_like numerical_query
58
58
  potential_matches.reject! { |m| m.to_s == exact_match.to_s } if exact_match
59
-
59
+
60
60
  new_calculated_match :query => query, :exact_matches => exact_match,
61
61
  :potential_matches => potential_matches
62
62
  else
@@ -11,7 +11,7 @@ module Adhearsion
11
11
  attr_reader :builder, :timeout, :tries_count, :max_number_of_tries
12
12
  def initialize(options={}, &block)
13
13
  @tries_count = 0 # Counts the number of tries the menu's been executed
14
-
14
+
15
15
  @timeout = options[:timeout] || DEFAULT_TIMEOUT
16
16
  @max_number_of_tries = options[:tries] || DEFAULT_MAX_NUMBER_OF_TRIES
17
17
 
@@ -24,15 +24,15 @@ module Adhearsion
24
24
  def <<(other)
25
25
  digit_buffer << other
26
26
  end
27
-
27
+
28
28
  def digit_buffer
29
29
  @digit_buffer
30
30
  end
31
-
31
+
32
32
  def digit_buffer_string
33
33
  digit_buffer.to_s
34
34
  end
35
-
35
+
36
36
  def digit_buffer_empty?
37
37
  digit_buffer.empty?
38
38
  end
@@ -79,8 +79,8 @@ module Adhearsion
79
79
  end
80
80
 
81
81
  protected
82
-
83
- # If you're using a more complex class in subclasses, you may want to override this method in addition to the
82
+
83
+ # If you're using a more complex class in subclasses, you may want to override this method in addition to the
84
84
  # digit_buffer, digit_buffer_empty, and digit_buffer_string methods
85
85
  def initialize_digit_buffer
86
86
  @digit_buffer = ClearableStringBuffer.new
@@ -131,17 +131,17 @@ module Adhearsion
131
131
  # Raised when the user's input matches no patterns
132
132
  class MenuResultInvalid < MenuResult; end
133
133
 
134
- # For our default purposes, we need the digit_buffer to behave much like a normal String except that it should
134
+ # For our default purposes, we need the digit_buffer to behave much like a normal String except that it should
135
135
  # handle its own resetting (clearing).
136
136
  class ClearableStringBuffer < String
137
137
  def clear!
138
138
  replace ""
139
139
  end
140
-
140
+
141
141
  def <<(other)
142
142
  super other.to_s
143
143
  end
144
-
144
+
145
145
  end
146
146
 
147
147
  end
@@ -9,11 +9,11 @@ require 'theatre/invocation'
9
9
  require 'theatre/callback_definition_loader'
10
10
 
11
11
  module Theatre
12
-
12
+
13
13
  class Theatre
14
-
14
+
15
15
  attr_reader :namespace_manager
16
-
16
+
17
17
  ##
18
18
  # Creates a new stopped Theatre. You must call start!() after you instantiate this for it to begin processing events.
19
19
  #
@@ -27,7 +27,7 @@ module Theatre
27
27
  @master_queue = Queue.new
28
28
  @loader_mixins = []
29
29
  end
30
-
30
+
31
31
  ##
32
32
  # Send a message to this Theatre for asynchronous processing.
33
33
  #
@@ -48,10 +48,10 @@ module Theatre
48
48
  invocation
49
49
  end
50
50
  end
51
-
51
+
52
52
  ##
53
53
  # Send a message to this Theatre for synchronous processing. The execution of this will not go through this Theatre's
54
- # Thread pool. If an error occurred in any of callbacks, the Exception object will be placed in the returned Array
54
+ # Thread pool. If an error occurred in any of callbacks, the Exception object will be placed in the returned Array
55
55
  # instead for you to act upon.
56
56
  #
57
57
  # @param [String] namespace The namespace to which the payload should be sent
@@ -72,29 +72,29 @@ module Theatre
72
72
  end
73
73
  end
74
74
  end
75
-
75
+
76
76
  def load_events_code(code, *args)
77
77
  loader = CallbackDefinitionLoader.new(self, *args)
78
78
  loader.load_events_code code
79
79
  end
80
-
80
+
81
81
  def load_events_file(file, *args)
82
82
  loader = CallbackDefinitionLoader.new(self, *args)
83
83
  loader.load_events_file file
84
84
  end
85
-
85
+
86
86
  def register_namespace_name(*args)
87
87
  @namespace_manager.register_namespace_name(*args)
88
88
  end
89
-
89
+
90
90
  def register_callback_at_namespace(*args)
91
91
  @namespace_manager.register_callback_at_namespace(*args)
92
92
  end
93
-
93
+
94
94
  def register_loader_mixin(mod)
95
95
  @loader_mixins << mod
96
96
  end
97
-
97
+
98
98
  def join
99
99
  @thread_group.list.each do |thread|
100
100
  begin
@@ -104,7 +104,7 @@ module Theatre
104
104
  end
105
105
  end
106
106
  end
107
-
107
+
108
108
  ##
109
109
  # Starts this Theatre.
110
110
  #
@@ -117,7 +117,7 @@ module Theatre
117
117
  @thread_group.add Thread.new(&method(:thread_loop))
118
118
  end
119
119
  end
120
-
120
+
121
121
  ##
122
122
  # Notifies all Threads for this Theatre to stop by sending them special messages. Any messages which were queued and
123
123
  # untriggered when this method is received will still be processed. Note: you may start this Theatre again later once it
@@ -127,14 +127,14 @@ module Theatre
127
127
  @thread_count.times { @master_queue << :THEATRE_SHUTDOWN! }
128
128
  @started_time = nil
129
129
  end
130
-
130
+
131
131
  protected
132
-
132
+
133
133
  # This will use the Adhearsion logger eventually.
134
134
  def warn(exception)
135
135
  # STDERR.puts exception.message, *exception.backtrace
136
136
  end
137
-
137
+
138
138
  def thread_loop
139
139
  loop do
140
140
  begin
@@ -146,6 +146,6 @@ module Theatre
146
146
  end
147
147
  end
148
148
  end
149
-
149
+
150
150
  end
151
151
  end
@@ -1,22 +1,22 @@
1
1
  module Theatre
2
-
2
+
3
3
  ##
4
4
  # This class provides the a wrapper aroung which an events.rb file can be instance_eval'd.
5
5
  #
6
6
  class CallbackDefinitionLoader
7
-
7
+
8
8
  attr_reader :theatre, :root_name
9
9
  def initialize(theatre, root_name=:events)
10
10
  @theatre = theatre
11
11
  @root_name = root_name
12
-
12
+
13
13
  create_recorder_method root_name
14
14
  end
15
-
15
+
16
16
  def anonymous_recorder
17
17
  BlankSlateMessageRecorder.new(&method(:callback_registered))
18
18
  end
19
-
19
+
20
20
  ##
21
21
  # Parses the given Ruby source code file and returns this object.
22
22
  #
@@ -27,7 +27,7 @@ module Theatre
27
27
  instance_eval file.read, file.path
28
28
  self
29
29
  end
30
-
30
+
31
31
  ##
32
32
  # Parses the given Ruby source code and returns this object.
33
33
  #
@@ -41,9 +41,9 @@ module Theatre
41
41
  instance_eval code
42
42
  self
43
43
  end
44
-
44
+
45
45
  protected
46
-
46
+
47
47
  ##
48
48
  # Immediately register the namespace and callback with the Theatre instance given to the constructor. This method is only
49
49
  # called when a new BlankSlateMessageRecorder is instantiated and receives #each().
@@ -51,34 +51,34 @@ module Theatre
51
51
  def callback_registered(namespaces, callback)
52
52
  # Get rid of all arguments passed to the namespaces. Will support arguments in the future.
53
53
  namespaces = namespaces.map { |namespace| namespace.first }
54
-
54
+
55
55
  theatre.namespace_manager.register_callback_at_namespace namespaces, callback
56
56
  end
57
-
57
+
58
58
  def create_recorder_method(record_method_name)
59
59
  (class << self; self; end).send(:alias_method, record_method_name, :anonymous_recorder)
60
60
  end
61
-
61
+
62
62
  class BlankSlateMessageRecorder
63
-
63
+
64
64
  (instance_methods - %w[__send__ __id__]).each { |m| undef_method m }
65
-
65
+
66
66
  def initialize(&notify_on_completion)
67
67
  @notify_on_completion = notify_on_completion
68
68
  @namespaces = []
69
69
  end
70
-
70
+
71
71
  def method_missing(*method_name_and_args)
72
72
  raise ArgumentError, "Supplying a block is not supported" if block_given?
73
73
  @namespaces << method_name_and_args
74
74
  self
75
75
  end
76
-
76
+
77
77
  def each(&callback)
78
78
  @notify_on_completion.call(@namespaces, callback)
79
79
  end
80
-
80
+
81
81
  end
82
-
82
+
83
83
  end
84
84
  end
@@ -2,19 +2,19 @@
2
2
  # Theatre depends and make that a dependent library.
3
3
 
4
4
  unless respond_to? :new_guid
5
-
5
+
6
6
  def random_character
7
7
  case random_digit = rand(62)
8
- when 0...10 : random_digit.to_s
9
- when 10...36 : (random_digit + 55).chr
10
- when 36...62 : (random_digit + 61).chr
8
+ when 0...10 then random_digit.to_s
9
+ when 10...36 then (random_digit + 55).chr
10
+ when 36...62 then (random_digit + 61).chr
11
11
  end
12
12
  end
13
-
13
+
14
14
  def random_string(length_of_string=8)
15
15
  Array.new(length_of_string) { random_character }.join
16
16
  end
17
-
17
+
18
18
  # This GUID implementation doesn't adhere to the RFC which wants to make certain segments based on the MAC address of a
19
19
  # network interface card and other wackiness. It's sufficiently random for our needs.
20
20
  def new_guid
@@ -3,16 +3,16 @@ require 'thread'
3
3
  require 'monitor'
4
4
 
5
5
  module Theatre
6
-
6
+
7
7
  ##
8
8
  # An Invocation is an object which Theatre generates and returns from Theatre#trigger.
9
9
  #
10
10
  class Invocation
11
-
11
+
12
12
  attr_reader :queued_time, :started_time, :finished_time, :unique_id, :callback, :namespace, :error, :returned_value
13
-
13
+
14
14
  class InvalidStateError < Exception; end
15
-
15
+
16
16
  ##
17
17
  # Create a new Invocation.
18
18
  #
@@ -27,14 +27,14 @@ module Theatre
27
27
  @callback = callback
28
28
  @current_state = :new
29
29
  @state_lock = Mutex.new
30
-
30
+
31
31
  # Used just to protect access to the @returned_value instance variable
32
32
  @returned_value_lock = Monitor.new
33
-
33
+
34
34
  # Used when wait() is called to notify all waiting threads by using a ConditionVariable
35
35
  @returned_value_blocker = @returned_value_lock.new_cond#Monitor::ConditionVariable.new @returned_value_lock
36
36
  end
37
-
37
+
38
38
  def queued
39
39
  with_state_lock do
40
40
  raise InvalidStateError unless @current_state == :new
@@ -43,18 +43,18 @@ module Theatre
43
43
  end
44
44
  true
45
45
  end
46
-
46
+
47
47
  def current_state
48
48
  with_state_lock { @current_state }
49
49
  end
50
-
50
+
51
51
  def start
52
52
  with_state_lock do
53
53
  raise InvalidStateError unless @current_state == :queued
54
54
  @current_state = :running
55
55
  end
56
56
  @started_time = Time.now.freeze
57
-
57
+
58
58
  begin
59
59
  self.returned_value = if @payload.equal? :theatre_no_payload
60
60
  @callback.call
@@ -68,20 +68,20 @@ module Theatre
68
68
  @finished_time = Time.now.freeze
69
69
  end
70
70
  end
71
-
71
+
72
72
  def execution_duration
73
73
  return nil unless @finished_time
74
74
  @finished_time - @started_time
75
75
  end
76
-
76
+
77
77
  def error?
78
78
  current_state.equal? :error
79
79
  end
80
-
80
+
81
81
  def success?
82
82
  current_state.equal? :success
83
83
  end
84
-
84
+
85
85
  ##
86
86
  # When this Invocation has been queued, started, and entered either the :success or :error state, this method will
87
87
  # finally return. Until then, it blocks the Thread.
@@ -94,9 +94,9 @@ module Theatre
94
94
  # Return the returned_value
95
95
  with_returned_value_lock { @returned_value }
96
96
  end
97
-
97
+
98
98
  protected
99
-
99
+
100
100
  ##
101
101
  # Protected setter which does some other housework when the returned value is found (such as notifying wait()ers)
102
102
  #
@@ -108,14 +108,14 @@ module Theatre
108
108
  @returned_value_blocker.broadcast
109
109
  end
110
110
  end
111
-
111
+
112
112
  def with_returned_value_lock(&block)
113
113
  @returned_value_lock.synchronize(&block)
114
114
  end
115
-
115
+
116
116
  def with_state_lock(&block)
117
117
  @state_lock.synchronize(&block)
118
118
  end
119
-
119
+
120
120
  end
121
121
  end
@@ -1,17 +1,17 @@
1
1
  module Theatre
2
-
2
+
3
3
  ##
4
4
  # Manages the hierarchial namespaces of a Theatre. This class is Thread-safe.
5
5
  #
6
6
  class ActorNamespaceManager
7
7
 
8
8
  VALID_NAMESPACE = %r{^(/[\w_]+)+$}
9
-
9
+
10
10
  class << self
11
11
  def valid_namespace_path?(namespace_path)
12
12
  namespace_path =~ VALID_NAMESPACE
13
13
  end
14
-
14
+
15
15
  ##
16
16
  # Since there are a couple ways to represent namespaces, this is a helper method which will normalize
17
17
  # them into the most practical: an Array of Symbols
@@ -25,13 +25,13 @@ module Theatre
25
25
  end
26
26
 
27
27
  end
28
-
28
+
29
29
  def initialize
30
30
  @registry_lock = Mutex.new
31
31
  @root = RootNamespaceNode.new
32
32
  end
33
-
34
- ##
33
+
34
+ ##
35
35
  # Have this registry recognize a new path and prepare it for callback registrations. All path segements will be created
36
36
  # in order. For example, when registering "/foo/bar/qaz" when no namespaces at all have been registered, this method will
37
37
  # first register "foo", then "bar", then "qaz". If the namespace was already registered, it will not be affected.
@@ -42,12 +42,12 @@ module Theatre
42
42
  #
43
43
  def register_namespace_name(*paths)
44
44
  paths = self.class.normalize_path_to_array paths
45
-
45
+
46
46
  paths.inject(@root) do |node, name|
47
47
  node.register_namespace_name name
48
48
  end
49
49
  end
50
-
50
+
51
51
  ##
52
52
  # Returns a Proc found after searching with the namespace you provide
53
53
  #
@@ -56,7 +56,7 @@ module Theatre
56
56
  def callbacks_for_namespaces(*paths)
57
57
  search_for_namespace(paths).callbacks
58
58
  end
59
-
59
+
60
60
  ##
61
61
  # Find a namespace in the tree.
62
62
  #
@@ -66,7 +66,7 @@ module Theatre
66
66
  def search_for_namespace(paths)
67
67
  paths = self.class.normalize_path_to_array paths
68
68
  path_string = "/"
69
-
69
+
70
70
  found_namespace = paths.inject(@root) do |last_node,this_node_name|
71
71
  raise NamespaceNotFound.new(path_string) if last_node.nil?
72
72
  path_string << this_node_name.to_s
@@ -75,64 +75,64 @@ module Theatre
75
75
  raise NamespaceNotFound.new("/#{paths.join('/')}") unless found_namespace
76
76
  found_namespace
77
77
  end
78
-
78
+
79
79
  ##
80
80
  # Registers the given callback at a namespace, assuming the namespace was already registered.
81
81
  #
82
82
  # @param [Array] paths Must be an Array of segments
83
- # @param [Proc] callback
83
+ # @param [Proc] callback
84
84
  # @raise NamespaceNotFound if a segment has not been registered yet
85
85
  #
86
86
  def register_callback_at_namespace(paths, callback)
87
87
  raise ArgumentError, "callback must be a Proc" unless callback.kind_of? Proc
88
88
  search_for_namespace(paths).register_callback callback
89
89
  end
90
-
90
+
91
91
  protected
92
-
92
+
93
93
  ##
94
- # Used by NamespaceManager to build a tree of namespaces. Has a Hash of children which is not
94
+ # Used by NamespaceManager to build a tree of namespaces. Has a Hash of children which is not
95
95
  # Thread-safe. For Thread-safety, all access should semaphore through the NamespaceManager.
96
96
  class NamespaceNode
97
-
97
+
98
98
  attr_reader :name
99
99
  def initialize(name)
100
100
  @name = name.freeze
101
101
  @children = {}
102
102
  @callbacks = []
103
103
  end
104
-
104
+
105
105
  def register_namespace_name(name)
106
106
  @children[name] ||= NamespaceNode.new(name)
107
107
  end
108
-
108
+
109
109
  def register_callback(callback)
110
110
  @callbacks << callback
111
111
  callback
112
112
  end
113
-
113
+
114
114
  def callbacks
115
115
  @callbacks.clone
116
116
  end
117
-
117
+
118
118
  def delete_callback(callback)
119
119
  @callbacks.delete callback
120
120
  end
121
-
121
+
122
122
  def child_named(name)
123
123
  @children[name]
124
124
  end
125
-
125
+
126
126
  def destroy_namespace(name)
127
127
  @children.delete name
128
128
  end
129
-
129
+
130
130
  def root?
131
131
  false
132
132
  end
133
-
133
+
134
134
  end
135
-
135
+
136
136
  class RootNamespaceNode < NamespaceNode
137
137
  def initialize
138
138
  super :ROOT
@@ -141,13 +141,13 @@ module Theatre
141
141
  true
142
142
  end
143
143
  end
144
-
144
+
145
145
  end
146
-
146
+
147
147
  class NamespaceNotFound < Exception
148
148
  def initialize(full_path)
149
149
  super "Could not find #{full_path.inspect} in the namespace registry. Did you register it yet?"
150
150
  end
151
151
  end
152
-
152
+
153
153
  end