restfulie 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/Gemfile +10 -5
  2. data/Rakefile +5 -2
  3. data/lib/restfulie.rb +10 -5
  4. data/lib/restfulie/client.rb +13 -9
  5. data/lib/restfulie/client/base.rb +24 -65
  6. data/lib/restfulie/client/configuration.rb +62 -64
  7. data/lib/restfulie/client/entry_point.rb +36 -0
  8. data/lib/restfulie/client/ext/atom_ext.rb +12 -0
  9. data/lib/restfulie/client/ext/http_ext.rb +22 -0
  10. data/lib/restfulie/client/ext/json_ext.rb +12 -0
  11. data/lib/restfulie/client/ext/xml_ext.rb +4 -0
  12. data/lib/restfulie/client/http.rb +25 -13
  13. data/lib/restfulie/client/http/cache.rb +22 -22
  14. data/lib/restfulie/client/http/error.rb +70 -70
  15. data/lib/restfulie/client/http/link_request_builder.rb +15 -0
  16. data/lib/restfulie/client/http/request_adapter.rb +209 -0
  17. data/lib/restfulie/client/http/request_builder.rb +107 -0
  18. data/lib/restfulie/client/http/request_builder_executor.rb +24 -0
  19. data/lib/restfulie/client/http/request_executor.rb +17 -0
  20. data/lib/restfulie/client/http/request_follow.rb +42 -0
  21. data/lib/restfulie/client/http/request_follow_executor.rb +10 -0
  22. data/lib/restfulie/client/http/request_history.rb +69 -0
  23. data/lib/restfulie/client/http/request_history_executor.rb +10 -0
  24. data/lib/restfulie/client/http/request_marshaller.rb +127 -0
  25. data/lib/restfulie/client/http/request_marshaller_executor.rb +10 -0
  26. data/lib/restfulie/client/http/response.rb +23 -0
  27. data/lib/restfulie/client/http/response_handler.rb +67 -0
  28. data/lib/restfulie/client/http/response_holder.rb +9 -0
  29. data/lib/restfulie/client/mikyung.rb +17 -14
  30. data/lib/restfulie/client/mikyung/concatenator.rb +15 -12
  31. data/lib/restfulie/client/mikyung/core.rb +65 -39
  32. data/lib/restfulie/client/mikyung/languages.rb +8 -26
  33. data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
  34. data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
  35. data/lib/restfulie/client/mikyung/rest_process_model.rb +184 -107
  36. data/lib/restfulie/client/mikyung/steady_state_walker.rb +34 -28
  37. data/lib/restfulie/client/mikyung/then_condition.rb +33 -27
  38. data/lib/restfulie/client/mikyung/when_condition.rb +53 -49
  39. data/lib/restfulie/common.rb +7 -12
  40. data/lib/restfulie/common/converter.rb +20 -9
  41. data/lib/restfulie/common/converter/atom.rb +8 -83
  42. data/lib/restfulie/common/converter/atom/base.rb +89 -0
  43. data/lib/restfulie/common/converter/atom/builder.rb +101 -99
  44. data/lib/restfulie/common/converter/atom/helpers.rb +16 -8
  45. data/lib/restfulie/common/converter/json.rb +12 -0
  46. data/lib/restfulie/common/converter/json/base.rb +84 -0
  47. data/lib/restfulie/common/converter/json/builder.rb +102 -0
  48. data/lib/restfulie/common/converter/json/helpers.rb +17 -0
  49. data/lib/restfulie/common/converter/values.rb +30 -26
  50. data/lib/restfulie/common/converter/xml.rb +14 -0
  51. data/lib/restfulie/common/converter/xml/base.rb +61 -0
  52. data/lib/restfulie/common/converter/xml/builder.rb +112 -0
  53. data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
  54. data/lib/restfulie/common/converter/xml/link.rb +25 -0
  55. data/lib/restfulie/common/converter/xml/links.rb +25 -0
  56. data/lib/restfulie/common/core_ext.rb +1 -5
  57. data/lib/restfulie/common/core_ext/hash.rb +12 -0
  58. data/lib/restfulie/common/error.rb +19 -0
  59. data/lib/restfulie/common/logger.rb +17 -9
  60. data/lib/restfulie/common/representation.rb +9 -10
  61. data/lib/restfulie/common/representation/atom.rb +15 -47
  62. data/lib/restfulie/common/representation/atom/base.rb +122 -365
  63. data/lib/restfulie/common/representation/atom/category.rb +41 -0
  64. data/lib/restfulie/common/representation/atom/entry.rb +52 -100
  65. data/lib/restfulie/common/representation/atom/factory.rb +43 -0
  66. data/lib/restfulie/common/representation/atom/feed.rb +103 -99
  67. data/lib/restfulie/common/representation/atom/link.rb +68 -0
  68. data/lib/restfulie/common/representation/atom/person.rb +48 -0
  69. data/lib/restfulie/common/representation/atom/source.rb +59 -0
  70. data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
  71. data/lib/restfulie/common/representation/atom/xml.rb +95 -0
  72. data/lib/restfulie/common/representation/generic.rb +30 -29
  73. data/lib/restfulie/common/representation/json.rb +10 -22
  74. data/lib/restfulie/common/representation/json/base.rb +27 -0
  75. data/lib/restfulie/common/representation/json/keys_as_methods.rb +72 -0
  76. data/lib/restfulie/common/representation/json/link.rb +29 -0
  77. data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
  78. data/lib/restfulie/common/representation/xml.rb +18 -227
  79. data/lib/restfulie/server.rb +9 -10
  80. data/lib/restfulie/server/action_controller.rb +10 -12
  81. data/lib/restfulie/server/action_controller/base.rb +18 -15
  82. data/lib/restfulie/server/action_controller/{routing/patch.rb → patch.rb} +0 -0
  83. data/lib/restfulie/server/action_controller/restful_responder.rb +43 -35
  84. data/lib/restfulie/server/action_view.rb +8 -6
  85. data/lib/restfulie/server/action_view/helpers.rb +47 -41
  86. data/lib/restfulie/server/action_view/template_handlers.rb +24 -12
  87. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +17 -12
  88. data/lib/restfulie/server/configuration.rb +22 -19
  89. data/lib/restfulie/server/{restfulie_controller.rb → controller.rb} +1 -10
  90. data/lib/restfulie/server/core_ext.rb +1 -1
  91. data/lib/restfulie/version.rb +14 -0
  92. metadata +52 -16
  93. data/lib/restfulie/client/http/adapter.rb +0 -502
  94. data/lib/restfulie/client/http/atom_ext.rb +0 -4
  95. data/lib/restfulie/client/http/core_ext.rb +0 -6
  96. data/lib/restfulie/client/http/core_ext/http.rb +0 -19
  97. data/lib/restfulie/client/http/marshal.rb +0 -145
  98. data/lib/restfulie/client/http/xml_ext.rb +0 -7
  99. data/lib/restfulie/common/core_ext/proc.rb +0 -48
  100. data/lib/restfulie/common/errors.rb +0 -15
  101. data/lib/restfulie/server/action_controller/routing.rb +0 -12
  102. data/lib/restfulie/server/action_controller/routing/restful_route.rb +0 -14
@@ -1,15 +1,18 @@
1
- # Concatenates pure text in order to build messages
2
- # that are used as patterns.
3
- # Usage:
4
- # When there is a machine
5
- #
6
- # Will invoke concatenate 'machine' with 'a' with 'is' with 'there'
7
- class Restfulie::Client::Mikyung::Concatenator
8
- attr_reader :content
9
- def initialize(content, *args)
10
- @content = content
11
- args.each do |arg|
12
- @content << " " << arg.content
1
+ module Restfulie
2
+ module Client
3
+ module Mikyung
4
+ # Concatenates pure text in order to build messages
5
+ # that are used as patterns.
6
+ # Usage:
7
+ # When there is a machine
8
+ #
9
+ # Will invoke concatenate 'machine' with 'a' with 'is' with 'there'
10
+ class Concatenator
11
+ attr_reader :content
12
+ def initialize(content, *args)
13
+ @content = args.inject(content) { |buf, arg| buf << " " << arg.content }
14
+ end
15
+ end
13
16
  end
14
17
  end
15
18
  end
@@ -1,44 +1,70 @@
1
- # iterates following a series of steps provided a goal and a starting uri.
2
- #
3
- # Restfulie::Client::Mikyung.achieve(objective).at(uri).run
4
- #
5
- # In order to implement your own walker, supply an object that respond to the move method.
6
- # Check the run method code.
7
- class Restfulie::Client::Mikyung::Core
8
-
9
- attr_reader :start, :goal, :walker
10
-
11
- def initialize
12
- @walker = Restfulie::Client::Mikyung::SteadyStateWalker.new
13
- end
14
-
15
- def walks_with(walker)
16
- @walker = walker
17
- self
18
- end
1
+ module Restfulie
2
+ module Client
3
+ module Mikyung
4
+ # iterates following a series of steps provided a goal and a starting uri.
5
+ #
6
+ # Restfulie::Client::Mikyung.achieve(objective).at(uri).run
7
+ #
8
+ # In order to implement your own walker, supply an object that respond to the move method.
9
+ # Check the run method code.
10
+ class Core
11
+ attr_reader :start, :goal, :walker, :accepts, :follow
12
+
13
+ def initialize
14
+ @walker = Restfulie::Client::Mikyung::SteadyStateWalker.new
15
+ end
16
+
17
+ def walks_with(walker)
18
+ @walker = walker
19
+ self
20
+ end
21
+
22
+ # initializes with a goal in mind
23
+ def achieve(goal)
24
+ @goal = goal
25
+ self
26
+ end
27
+
28
+ def at(start)
29
+ @start = start
30
+ self
31
+ end
19
32
 
20
- # initializes with a goal in mind
21
- def achieve(goal)
22
- @goal = goal
23
- self
24
- end
25
-
26
- def at(start)
27
- @start = start
28
- self
29
- end
33
+ def follow
34
+ @follow = true
35
+ self
36
+ end
30
37
 
31
- # keeps changing from a steady state to another until its goal has been achieved
32
- def run
33
- @start = current = (@start.kind_of? String) ? Restfulie.at(@start).get : @start
34
-
35
- while(!@goal.completed?(current))
36
- current = @walker.move(@goal, current, self)
38
+ def accepts(accepts)
39
+ @accepts = accepts
40
+ self
41
+ end
42
+
43
+ # keeps changing from a steady state to another until its goal has been achieved
44
+ def run
45
+ if @start.kind_of? String
46
+ client = Restfulie.at(@start)
47
+ client = client.follow if @follow
48
+ client = client.accepts(@accepts) if @accepts
49
+ @start = current = client.get
50
+ else
51
+ # probably configured thru the Rest Process Model class
52
+ @start = current = @goal.class.get_restfulie.get
53
+ end
54
+
55
+ # load the steps and scenario
56
+ @goal.steps
57
+ @goal.scenario
58
+
59
+ while(!@goal.completed?(current))
60
+ current = @walker.move(@goal, current, self)
61
+ end
62
+ current
63
+ end
64
+ end
37
65
  end
38
- current
39
- end
40
-
41
- end
42
66
 
43
- class Restfulie::Client::UnableToAchieveGoalError < Restfulie::Common::Error::RestfulieError
67
+ class UnableToAchieveGoalError < Restfulie::Common::Error::RestfulieError
68
+ end
69
+ end
44
70
  end
@@ -1,29 +1,11 @@
1
- module Restfulie::Client::Mikyung::German
2
- def Wenn(concat, &block)
3
- When(concat, &block)
4
- end
5
- def Und(concat, &block)
6
- And(concat, &block)
7
- end
8
- def Aber(concat, &block)
9
- But(concat, &block)
10
- end
11
- def Dann(concat, &block)
12
- Then(concat, &block)
1
+ module Restfulie
2
+ module Client
3
+ module Mikyung
4
+ module Languages
5
+ autoload :German, 'restfulie/client/mikyung/german'
6
+ autoload :Portuguese, 'restfulie/client/mikyung/portuguese'
7
+ end
8
+ end
13
9
  end
14
10
  end
15
11
 
16
- module Restfulie::Client::Mikyung::Portuguese
17
- def Quando(concat, &block)
18
- When(concat, &block)
19
- end
20
- def E(concat, &block)
21
- And(concat, &block)
22
- end
23
- def Mas(concat, &block)
24
- But(concat, &block)
25
- end
26
- def Entao(concat, &block)
27
- Then(concat, &block)
28
- end
29
- end
@@ -0,0 +1,24 @@
1
+ module Restfulie
2
+ module Client
3
+ module Mikyung
4
+ module Languages
5
+ module German
6
+ def Wenn(concat, &block)
7
+ When(concat, &block)
8
+ end
9
+ def Und(concat, &block)
10
+ And(concat, &block)
11
+ end
12
+ def Aber(concat, &block)
13
+ But(concat, &block)
14
+ end
15
+ def Dann(concat, &block)
16
+ Then(concat, &block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,23 @@
1
+ module Restfulie
2
+ module Client
3
+ module Mikyung
4
+ module Languages
5
+ module Portuguese
6
+ def Quando(concat, &block)
7
+ When(concat, &block)
8
+ end
9
+ def E(concat, &block)
10
+ And(concat, &block)
11
+ end
12
+ def Mas(concat, &block)
13
+ But(concat, &block)
14
+ end
15
+ def Entao(concat, &block)
16
+ Then(concat, &block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -1,114 +1,191 @@
1
1
  # a configuration error
2
- class Restfulie::Client::Mikyung::ConfigurationError < Restfulie::Common::Error::RestfulieError
3
- end
2
+ module Restfulie
3
+ module Client
4
+ module Mikyung
5
+ class ConfigurationError < Restfulie::Common::Error::RestfulieError
6
+ end
4
7
 
5
- # Provides a DSL to build your process in a human readable way.
6
- #
7
- # Example:
8
- # When there is a machine
9
- # And already installed
10
- # Then reboot
11
- #
12
- # Before creating your DSL you should provide your method content:
13
- #
14
- # When /there (are|is an|is a|is) (.*)/ do |resource, regex|
15
- # resource.keys.first==regex[2]
16
- # end
17
- #
18
- # When "already installed" do |resource|
19
- # @installed
20
- # end
21
- #
22
- # Then "reboot" do |resource|
23
- # resource.machine.boot.post! :boot => {:reason => "Installed #{@software[:name]}"}
24
- # end
25
- class Restfulie::Client::Mikyung::RestProcessModel
26
-
27
- # concatenates anything to a current expression
28
- def method_missing(sym, *args)
29
- Restfulie::Client::Mikyung::Concatenator.new(sym.to_s, *args)
30
- end
31
-
32
- # the list of results
33
- def then_rules
34
- @then_rules ||= []
35
- end
36
-
37
- # the list of conditions
38
- def conditions
39
- @conditions ||= []
40
- end
41
-
42
- # the list of conditional rules
43
- def when_rules
44
- @when_rules ||= []
45
- end
46
-
47
- # creates a When rule or block
48
- #
49
- # When blocks should return true or false whether the current resource matches what you expect:
50
- # When /there (are|is an|is a|is) (.*)/ do |resource, regex|
51
- # resource.keys.first==regex[2]
52
- # end
53
- #
54
- # When rules will group conditions and rules together:
55
- # When there is a machine
56
- # And already installed
57
- # Then reboot
58
- def When(concat, &block)
59
- if concat.respond_to? :content
60
- @condition = when_factory(concat)
61
- conditions << @condition
62
- else
63
- when_rules << [concat, block]
64
- end
65
- end
66
-
67
- # Adds a constraint to the current scenario
68
- def And(concat)
69
- @condition.and when_factory(concat)
70
- end
71
-
72
- # Adds a negative constraint to the current scenario
73
- def But(concat)
74
- @condition.but when_factory(concat)
75
- end
76
-
77
- # Creates a result rule
78
- #
79
- # example:
80
- # Then "reboot" do |resource|
81
- # resource.machine.boot.post! :boot => {:reason => "Installed #{@software[:name]}"}
82
- # end
83
- def Then(concat, &block)
84
- if concat.respond_to? :content
85
- @condition.results_on Restfulie::Client::Mikyung::ThenCondition.new(concat.content)
86
- else
87
- then_rules << [concat, block]
88
- end
89
- end
8
+ class CompletionCriteriaMissingError < Restfulie::Common::Error::RestfulieError
9
+ end
90
10
 
91
- # Goes through every scenario and finds which one fits the current server steady state.
92
- # Picks this step and executes the business rule attached to it.
93
- def next_step(resource, mikyung)
94
- conditions.each do |c|
95
- if c.should_run_for(resource, self)
96
- return c.execute(resource, self, mikyung)
11
+ class StepsFileNotFoundError < Restfulie::Common::Error::RestfulieError
12
+ end
13
+
14
+ class ScenarioFileNotFoundError < StepsFileNotFoundError
15
+ end
16
+
17
+ # Provides a DSL to build your process in a human readable way.
18
+ #
19
+ # Example:
20
+ # When there is a machine
21
+ # And already installed
22
+ # Then reboot
23
+ #
24
+ # Before creating your DSL you should provide your method content:
25
+ #
26
+ # When /there (are|is an|is a|is) (.*)/ do |resource, regex|
27
+ # resource.keys.first==regex[2]
28
+ # end
29
+ #
30
+ # When "already installed" do |resource|
31
+ # @installed
32
+ # end
33
+ #
34
+ # Then "reboot" do |resource|
35
+ # resource.machine.boot.post! :boot => {:reason => "Installed #{@software[:name]}"}
36
+ # end
37
+ class RestProcessModel
38
+ @@at = ""
39
+ @@follow = false
40
+ @@accept = "application/atom+xml"
41
+ @@current_dir = ""
42
+
43
+ def self.at(uri)
44
+ @@at = uri
45
+ end
46
+
47
+ def self.follow(bool)
48
+ @@follow = bool
49
+ end
50
+
51
+ def self.accept(type)
52
+ @@accept = type
53
+ end
54
+
55
+ def self.current_dir(dir)
56
+ @@current_dir = dir
57
+ end
58
+
59
+ def self.get_restfulie
60
+ Restfulie.at(@@at).tap do |client|
61
+ client.follow if @@follow
62
+ client.accepts(@@accept) if @@accept
63
+ end
64
+ end
65
+
66
+ # concatenates anything to a current expression
67
+ def method_missing(sym, *args)
68
+ Restfulie::Client::Mikyung::Concatenator.new(sym.to_s, *args)
69
+ end
70
+
71
+ # the list of results
72
+ def then_rules
73
+ @then_rules ||= []
74
+ end
75
+
76
+ # the list of conditions
77
+ def conditions
78
+ @conditions ||= []
79
+ end
80
+
81
+ # the list of conditional rules
82
+ def when_rules
83
+ @when_rules ||= []
84
+ end
85
+
86
+ # creates a When rule or block
87
+ #
88
+ # When blocks should return true or false whether the current resource matches what you expect:
89
+ # When /there (are|is an|is a|is) (.*)/ do |resource, regex|
90
+ # resource.keys.first==regex[2]
91
+ # end
92
+ #
93
+ # When rules will group conditions and rules together:
94
+ # When there is a machine
95
+ # And already installed
96
+ # Then reboot
97
+ def When(concat, &block)
98
+ if concat.respond_to? :content
99
+ @condition = when_factory(concat)
100
+ conditions << @condition
101
+ else
102
+ when_rules << [concat, block]
103
+ end
104
+ end
105
+
106
+ # Adds a constraint to the current scenario
107
+ def And(concat)
108
+ @condition.and when_factory(concat)
109
+ end
110
+
111
+ # Adds a negative constraint to the current scenario
112
+ def But(concat)
113
+ @condition.but when_factory(concat)
114
+ end
115
+
116
+ # Creates a result rule
117
+ #
118
+ # example:
119
+ # Then "reboot" do |resource|
120
+ # resource.machine.boot.post! :boot => {:reason => "Installed #{@software[:name]}"}
121
+ # end
122
+ def Then(concat, &block)
123
+ if concat.respond_to? :content
124
+ @condition.results_on Restfulie::Client::Mikyung::ThenCondition.new(concat.content)
125
+ else
126
+ then_rules << [concat, block]
127
+ end
128
+ end
129
+
130
+ # Goes through every scenario and finds which one fits the current server steady state.
131
+ # Picks this step and executes the business rule attached to it.
132
+ def next_step(resource, mikyung)
133
+ conditions.each do |c|
134
+ if c.should_run_for(resource, self)
135
+ return c.execute(resource, self, mikyung)
136
+ end
137
+ end
138
+ nil
139
+ end
140
+
141
+ # load step definitions from the 'steps/[class_name].rb'
142
+ # otherwise you can simply override this method with a module
143
+ def steps
144
+ unless @steps_loaded
145
+ step_file = File.expand_path("./steps/#{self.class.name.underscore}.rb", @@current_dir)
146
+ if File.exists?(step_file)
147
+ self.instance_eval File.read(step_file), __FILE__, __LINE__ + 1
148
+ else
149
+ raise StepsFileNotFoundError.new("File #{step_file} not found")
150
+ end
151
+ @steps_loaded = true
152
+ end
153
+ end
154
+
155
+ # load scenario definition from 'scenarios/[class_name].scenario'
156
+ # otherwise you can simply override this method with a module
157
+ def scenario
158
+ unless @scenarios_loaded
159
+ scenario_file = File.expand_path("./scenarios/#{self.class.name.underscore}.scenario", @@current_dir)
160
+ if File.exists?(scenario_file)
161
+ self.instance_eval File.read(scenario_file), __FILE__, __LINE__ + 1
162
+ else
163
+ raise ScenarioFileNotFoundError.new("File #{scenario_file} not found")
164
+ end
165
+ @scenarios_loaded = true
166
+ end
167
+ end
168
+
169
+ # you need to override this method to provide a completion
170
+ # criteria. Will raise an error otherwise
171
+ def completed?(resource)
172
+ raise CompletionCriteriaMissingError.new
173
+ end
174
+
175
+ private
176
+
177
+ def when_factory(concat)
178
+ rule = when_rules.find do |rule|
179
+ concat.content.match(rule[0])
180
+ end
181
+ if rule.nil?
182
+ raise Restfulie::Client::Mikyung::ConfigurationError, "You forgot to create '#{concat.content}' prior to its usage."
183
+ end
184
+ Restfulie::Client::Mikyung::WhenCondition.new(concat.content, rule, concat.content.match(rule[0]))
185
+ end
97
186
  end
98
187
  end
99
- nil
100
- end
101
-
102
- private
103
-
104
- def when_factory(concat)
105
- rule = when_rules.find do |rule|
106
- concat.content.match(rule[0])
107
- end
108
- if rule.nil?
109
- raise Restfulie::Client::Mikyung::ConfigurationError, "You forgot to create '#{concat.content}' prior to its usage."
110
- end
111
- Restfulie::Client::Mikyung::WhenCondition.new(concat.content, rule, concat.content.match(rule[0]))
112
188
  end
113
-
114
189
  end
190
+
191
+