adhearsion 2.0.0.rc4 → 2.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/adhearsion.gemspec +1 -1
  3. data/bin/ahn +0 -3
  4. data/lib/adhearsion.rb +7 -4
  5. data/lib/adhearsion/call.rb +1 -1
  6. data/lib/adhearsion/call_controller.rb +1 -0
  7. data/lib/adhearsion/call_controller/menu_dsl.rb +19 -0
  8. data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +43 -0
  9. data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +45 -0
  10. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +22 -0
  11. data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +40 -0
  12. data/lib/adhearsion/call_controller/menu_dsl/menu.rb +203 -0
  13. data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +84 -0
  14. data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +60 -0
  15. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +25 -0
  16. data/lib/adhearsion/cli.rb +0 -1
  17. data/lib/adhearsion/router/route.rb +2 -2
  18. data/lib/adhearsion/version.rb +1 -1
  19. data/spec/adhearsion/call_controller/input_spec.rb +1 -1
  20. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +60 -0
  21. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +61 -0
  22. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +37 -0
  23. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +17 -0
  24. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +151 -0
  25. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +373 -0
  26. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +32 -0
  27. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +40 -0
  28. metadata +91 -91
  29. data/lib/adhearsion/menu_dsl.rb +0 -17
  30. data/lib/adhearsion/menu_dsl/calculated_match.rb +0 -41
  31. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +0 -43
  32. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +0 -20
  33. data/lib/adhearsion/menu_dsl/match_calculator.rb +0 -38
  34. data/lib/adhearsion/menu_dsl/menu.rb +0 -201
  35. data/lib/adhearsion/menu_dsl/menu_builder.rb +0 -82
  36. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +0 -58
  37. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +0 -23
  38. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +0 -58
  39. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +0 -59
  40. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +0 -35
  41. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +0 -15
  42. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +0 -149
  43. data/spec/adhearsion/menu_dsl/menu_spec.rb +0 -371
  44. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +0 -30
  45. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +0 -38
@@ -1,17 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
- extend ActiveSupport::Autoload
6
-
7
- autoload :Exceptions
8
- autoload :CalculatedMatch
9
- autoload :CalculatedMatchCollection
10
- autoload :MatchCalculator
11
- autoload :FixnumMatchCalculator
12
- autoload :RangeMatchCalculator
13
- autoload :StringMatchCalculator
14
- autoload :MenuBuilder
15
- autoload :Menu
16
- end
17
- end
@@ -1,41 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
- class CalculatedMatch
6
-
7
- def self.failed_match!(pattern, query, match_payload)
8
- new :pattern => pattern, :query => query, :match_payload => match_payload
9
- end
10
-
11
- attr_reader :match_payload, :potential_matches, :exact_matches, :pattern, :query, :block
12
-
13
- def initialize(options = {})
14
- @pattern, @query, @match_payload, @block = options.values_at :pattern, :query, :match_payload, :block
15
- @potential_matches = options[:potential_matches] ? Array(options[:potential_matches]) : []
16
- @exact_matches = options[:exact_matches] ? Array(options[:exact_matches]) : []
17
- end
18
-
19
- def exact_match?
20
- exact_matches.any?
21
- end
22
-
23
- def potential_match?
24
- potential_matches.any?
25
- end
26
-
27
- def failed_match?
28
- !(potential_match? || exact_match?)
29
- end
30
-
31
- def type_of_match
32
- if exact_match?
33
- :exact
34
- elsif potential_match?
35
- :potential
36
- end
37
- end
38
-
39
- end
40
- end
41
- end
@@ -1,43 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
- class CalculatedMatchCollection
6
- attr_reader :calculated_matches, :potential_matches, :exact_matches,
7
- :actual_potential_matches, :actual_exact_matches
8
-
9
- def initialize
10
- @calculated_matches = []
11
- @potential_matches = []
12
- @exact_matches = []
13
- @actual_potential_matches = []
14
- @actual_exact_matches = []
15
- end
16
-
17
- def <<(calculated_match)
18
- calculated_matches << calculated_match
19
- actual_potential_matches.concat calculated_match.potential_matches
20
- actual_exact_matches.concat calculated_match.exact_matches
21
-
22
- potential_matches << calculated_match if calculated_match.potential_match?
23
- exact_matches << calculated_match if calculated_match.exact_match?
24
- end
25
-
26
- def potential_match_count
27
- actual_potential_matches.size
28
- end
29
-
30
- def exact_match_count
31
- actual_exact_matches.size
32
- end
33
-
34
- def potential_match?
35
- potential_match_count > 0
36
- end
37
-
38
- def exact_match?
39
- exact_match_count > 0
40
- end
41
- end
42
- end
43
- end
@@ -1,20 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
- class FixnumMatchCalculator < MatchCalculator
6
-
7
- def match(query)
8
- numeric_query = coerce_to_numeric query
9
- exact_match, potential_match = nil
10
- if pattern == numeric_query
11
- exact_match = pattern
12
- elsif pattern.to_s.starts_with? query.to_s
13
- potential_match = pattern
14
- end
15
- new_calculated_match :query => query, :exact_matches => exact_match, :potential_matches => potential_match
16
- end
17
-
18
- end # class FixnumMatchCalculator
19
- end
20
- end
@@ -1,38 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
- class MatchCalculator
6
-
7
- class << self
8
-
9
- def build_with_pattern(pattern, match_payload, &block)
10
- class_for_pattern(pattern).new pattern, match_payload, &block
11
- end
12
-
13
- private
14
-
15
- def class_for_pattern(pattern)
16
- MenuDSL.const_get "#{pattern.class.name.camelize}MatchCalculator"
17
- end
18
- end
19
-
20
- attr_reader :pattern, :match_payload, :block
21
-
22
- def initialize(pattern, match_payload, &block)
23
- @pattern, @match_payload, @block = pattern, match_payload, block
24
- end
25
-
26
- protected
27
-
28
- def new_calculated_match(options)
29
- CalculatedMatch.new({:pattern => pattern, :match_payload => match_payload, :block => block}.merge(options))
30
- end
31
-
32
- def coerce_to_numeric(victim)
33
- victim.kind_of?(Numeric) ? victim : (victim.to_s =~ /^\d+$/ ? victim.to_s.to_i : nil )
34
- end
35
-
36
- end # class MatchCalculator
37
- end
38
- end
@@ -1,201 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
-
6
- class Menu
7
-
8
- DEFAULT_MAX_NUMBER_OF_TRIES = 1
9
- DEFAULT_TIMEOUT = 5
10
-
11
- InvalidStructureError = Class.new Adhearsion::Error
12
-
13
- attr_reader :builder, :timeout, :tries_count, :max_number_of_tries, :terminator, :limit, :interruptible, :status
14
-
15
- def initialize(options = {}, &block)
16
- @tries_count = 0 # Counts the number of tries the menu's been executed
17
- @timeout = options[:timeout] || DEFAULT_TIMEOUT
18
- @max_number_of_tries = options[:tries] || DEFAULT_MAX_NUMBER_OF_TRIES
19
- @terminator = options[:terminator].to_s
20
- @limit = options[:limit]
21
- @interruptible = options.has_key?(:interruptible) ? options[:interruptible] : true
22
- @builder = MenuDSL::MenuBuilder.new
23
- @terminated = false
24
-
25
- @builder.build(&block) if block
26
-
27
- initialize_digit_buffer
28
- end
29
-
30
- def validate(mode = nil)
31
- case mode
32
- when :basic
33
- @terminator.present? || !!@limit || raise(InvalidStructureError, "You must specify at least one of limit or terminator")
34
- else
35
- @builder.has_matchers? || raise(InvalidStructureError, "You must specify one or more matchers")
36
- end
37
- end
38
-
39
- def <<(other)
40
- if other == terminator
41
- @terminated = true
42
- else
43
- digit_buffer << other
44
- end
45
- end
46
-
47
- def digit_buffer
48
- @digit_buffer
49
- end
50
-
51
- def digit_buffer_string
52
- digit_buffer.to_s
53
- end
54
- alias :result :digit_buffer_string
55
-
56
- def digit_buffer_empty?
57
- digit_buffer.empty?
58
- end
59
-
60
- def continue
61
- return get_another_digit_or_timeout! if digit_buffer_empty?
62
-
63
- return menu_terminated! if @terminated
64
- return menu_limit_reached! if limit && digit_buffer.size >= limit
65
-
66
- return menu_validator_terminated! if execute_validator_hook
67
-
68
- calculated_matches = builder.calculate_matches_for digit_buffer_string
69
-
70
- if calculated_matches.exact_match_count >= 1
71
- first_exact_match = calculated_matches.exact_matches.first
72
- if calculated_matches.potential_match_count.zero?
73
- menu_result_found! first_exact_match, digit_buffer_string
74
- else
75
- get_another_digit_or_finish! first_exact_match.match_payload, first_exact_match.query
76
- end
77
- elsif calculated_matches.potential_match_count >= 1 || !@builder.has_matchers?
78
- get_another_digit_or_timeout!
79
- else
80
- invalid!
81
- end
82
- end
83
-
84
- def should_continue?
85
- tries_count < max_number_of_tries
86
- end
87
-
88
- def restart!
89
- @tries_count += 1
90
- digit_buffer.clear!
91
- end
92
-
93
- def execute_invalid_hook
94
- builder.execute_hook_for :invalid, digit_buffer_string
95
- end
96
-
97
- def execute_timeout_hook
98
- builder.execute_hook_for :timeout, digit_buffer_string
99
- end
100
-
101
- def execute_failure_hook
102
- builder.execute_hook_for :failure, digit_buffer_string
103
- end
104
-
105
- def execute_validator_hook
106
- builder.execute_hook_for :validator, digit_buffer_string
107
- end
108
-
109
- protected
110
-
111
- # If you're using a more complex class in subclasses, you may want to override this method in addition to the
112
- # digit buffer, digit_buffer_empty, and digit_buffer_string methods
113
- def initialize_digit_buffer
114
- @digit_buffer = ClearableStringBuffer.new
115
- end
116
-
117
- def invalid!
118
- @status = :invalid
119
- MenuResultInvalid.new
120
- end
121
-
122
- def menu_result_found!(match_object, new_extension)
123
- @status = :matched
124
- MenuResultFound.new(match_object, new_extension)
125
- end
126
-
127
- def menu_terminated!
128
- @status = :terminated
129
- MenuTerminated.new
130
- end
131
-
132
- def menu_validator_terminated!
133
- @status = :validator_terminated
134
- MenuValidatorTerminated.new
135
- end
136
-
137
- def menu_limit_reached!
138
- @status = :limited
139
- MenuLimitReached.new
140
- end
141
-
142
- def get_another_digit_or_finish!(match_payload, new_extension)
143
- @status = :multi_matched
144
- MenuGetAnotherDigitOrFinish.new(match_payload, new_extension)
145
- end
146
-
147
- def get_another_digit_or_timeout!
148
- @status = :potential
149
- MenuGetAnotherDigitOrTimeout.new
150
- end
151
-
152
- # The superclass from which all message-like exceptions descend. It should never
153
- # be instantiated directly.
154
- MenuResult = Class.new
155
- MenuResultDone = Class.new MenuResult
156
-
157
- class MenuResultFound < MenuResult
158
-
159
- attr_reader :match_object, :new_extension
160
-
161
- def initialize(match_object, new_extension)
162
- super()
163
- @match_object = match_object
164
- @new_extension = new_extension
165
- end
166
-
167
- end #class MenuResultFound < MenuResult
168
-
169
- MenuGetAnotherDigit = Module.new
170
-
171
- class MenuGetAnotherDigitOrFinish < MenuResultFound
172
- include MenuGetAnotherDigit
173
- end
174
-
175
- class MenuGetAnotherDigitOrTimeout < MenuResult
176
- include MenuGetAnotherDigit
177
- end
178
-
179
- MenuResultInvalid = Class.new MenuResult
180
-
181
- MenuTerminated = Class.new MenuResultDone
182
- MenuValidatorTerminated = Class.new MenuResultDone
183
- MenuLimitReached = Class.new MenuResultDone
184
-
185
- # For our default purpose, we need the digit_buffer to behave much like a normal String except that it should
186
- # handle its own resetting (clearing)
187
- class ClearableStringBuffer < String
188
- def clear!
189
- replace ""
190
- end
191
-
192
- def <<(other)
193
- super other.to_s
194
- end
195
- end
196
-
197
-
198
- end # class Menu
199
-
200
- end
201
- end
@@ -1,82 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Adhearsion
4
- module MenuDSL
5
-
6
- class MenuBuilder
7
-
8
- attr_accessor :patterns, :menu_callbacks
9
-
10
- def initialize
11
- @patterns = []
12
- @menu_callbacks = {}
13
- @context = nil
14
- end
15
-
16
- def build(&block)
17
- @context = eval "self", block.binding
18
- instance_eval(&block)
19
- end
20
-
21
- def match(*args, &block)
22
- payload = if block_given?
23
- raise ArgumentError, "You cannot specify both a block and a controller name." if args.last.is_a? Class
24
- nil
25
- else
26
- raise ArgumentError, "You need to provide a block or a controller name." unless args.last.is_a? Class
27
- args.pop
28
- end
29
-
30
- raise ArgumentError, "You cannot call this method without patterns." if args.empty?
31
-
32
- args.each do |pattern|
33
- @patterns << MatchCalculator.build_with_pattern(pattern, payload, &block)
34
- end
35
- end
36
-
37
- def weighted_match_calculators
38
- @patterns
39
- end
40
-
41
- def has_matchers?
42
- @patterns.size > 0
43
- end
44
-
45
- def execute_hook_for(symbol, input)
46
- callback = @menu_callbacks[symbol]
47
- return unless callback
48
- @context.instance_exec input, &callback
49
- end
50
-
51
- def invalid(&block)
52
- raise LocalJumpError, "Must supply a block!" unless block_given?
53
- @menu_callbacks[:invalid] = block
54
- end
55
-
56
- def timeout(&block)
57
- raise LocalJumpError, "Must supply a block!" unless block_given?
58
- @menu_callbacks[:timeout] = block
59
- end
60
-
61
- def failure(&block)
62
- raise LocalJumpError, "Must supply a block!" unless block_given?
63
- @menu_callbacks[:failure] = block
64
- end
65
-
66
- def validator(&block)
67
- raise LocalJumpError, "Must supply a block!" unless block_given?
68
- @menu_callbacks[:validator] = block
69
- end
70
-
71
- def calculate_matches_for(result)
72
- CalculatedMatchCollection.new.tap do |collection|
73
- weighted_match_calculators.each do |pattern|
74
- collection << pattern.match(result)
75
- end
76
- end
77
- end
78
-
79
- end # class MenuBuilder
80
-
81
- end
82
- end