waw 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. data/LICENCE.rdoc +25 -0
  2. data/README.rdoc +32 -0
  3. data/bin/waw +32 -0
  4. data/bin/waw-profile +26 -0
  5. data/bin/waw-start +26 -0
  6. data/bin/wspec +33 -0
  7. data/layouts/empty/Rakefile +14 -0
  8. data/layouts/empty/config.ru +5 -0
  9. data/layouts/empty/config/commons.cfg +31 -0
  10. data/layouts/empty/config/devel.cfg +21 -0
  11. data/layouts/empty/ignore +7 -0
  12. data/layouts/empty/logs/dontforgetme +0 -0
  13. data/layouts/empty/resources/messages.rs +1 -0
  14. data/layouts/empty/test/wspec/site_respond.wspec +3 -0
  15. data/layouts/empty/test/wspec/test_all.rb +13 -0
  16. data/layouts/empty/waw.deploy +1 -0
  17. data/layouts/empty/waw.routing +6 -0
  18. data/layouts/static/dependencies +1 -0
  19. data/layouts/static/public/.wawaccess +18 -0
  20. data/layouts/static/public/css/style.css +0 -0
  21. data/layouts/static/public/images/dontforgetme +0 -0
  22. data/layouts/static/public/js/project.js +0 -0
  23. data/layouts/static/public/pages/.wawaccess +30 -0
  24. data/layouts/static/public/pages/404.wtpl +1 -0
  25. data/layouts/static/public/pages/index.wtpl +5 -0
  26. data/layouts/static/public/templates/.wawaccess +9 -0
  27. data/layouts/static/public/templates/layout.wtpl +17 -0
  28. data/layouts/static/test/wspec/static_pages_are_served.wspec +21 -0
  29. data/layouts/static/waw.routing +8 -0
  30. data/lib/waw.rb +99 -0
  31. data/lib/waw/commands/command.rb +115 -0
  32. data/lib/waw/commands/profile_command.rb +66 -0
  33. data/lib/waw/commands/start_command.rb +59 -0
  34. data/lib/waw/config.rb +110 -0
  35. data/lib/waw/controller.rb +25 -0
  36. data/lib/waw/controllers/action/action.rb +91 -0
  37. data/lib/waw/controllers/action/action_utils.rb +30 -0
  38. data/lib/waw/controllers/action/js_generation.rb +116 -0
  39. data/lib/waw/controllers/action_controller.rb +133 -0
  40. data/lib/waw/controllers/error/backtrace.rb +54 -0
  41. data/lib/waw/controllers/error_handler.rb +62 -0
  42. data/lib/waw/controllers/json_controller.rb +31 -0
  43. data/lib/waw/controllers/no_cache.rb +22 -0
  44. data/lib/waw/controllers/static/match.rb +80 -0
  45. data/lib/waw/controllers/static/waw_access.rb +235 -0
  46. data/lib/waw/controllers/static/waw_access_dsl.rb +48 -0
  47. data/lib/waw/controllers/static_controller.rb +37 -0
  48. data/lib/waw/default_config.cfg +14 -0
  49. data/lib/waw/environment_utils.rb +57 -0
  50. data/lib/waw/errors.rb +4 -0
  51. data/lib/waw/ext.rb +3 -0
  52. data/lib/waw/ext/core.rb +4 -0
  53. data/lib/waw/ext/core/hash.rb +47 -0
  54. data/lib/waw/ext/core/logger.rb +10 -0
  55. data/lib/waw/ext/core/module.rb +20 -0
  56. data/lib/waw/ext/core/object.rb +29 -0
  57. data/lib/waw/ext/rack.rb +19 -0
  58. data/lib/waw/ext/rack/builder.rb +43 -0
  59. data/lib/waw/ext/rack/delegator.rb +51 -0
  60. data/lib/waw/ext/rack/urlmap.rb +55 -0
  61. data/lib/waw/ext/wlang.rb +1 -0
  62. data/lib/waw/ext/wlang/hosted_language.rb +21 -0
  63. data/lib/waw/fullstate.rb +8 -0
  64. data/lib/waw/fullstate/on_class.rb +37 -0
  65. data/lib/waw/fullstate/on_instance.rb +27 -0
  66. data/lib/waw/fullstate/variable.rb +36 -0
  67. data/lib/waw/kern.rb +6 -0
  68. data/lib/waw/kern/app.rb +48 -0
  69. data/lib/waw/kern/empty/waw.deploy +0 -0
  70. data/lib/waw/kern/empty/waw.routing +1 -0
  71. data/lib/waw/kern/freezed_state.rb +32 -0
  72. data/lib/waw/kern/hooks.rb +53 -0
  73. data/lib/waw/kern/lifecycle.rb +248 -0
  74. data/lib/waw/kern/living_state.rb +87 -0
  75. data/lib/waw/kern/utils.rb +27 -0
  76. data/lib/waw/resource_collection.rb +100 -0
  77. data/lib/waw/restart.rb +32 -0
  78. data/lib/waw/routing.rb +43 -0
  79. data/lib/waw/routing/action_routing.rb +78 -0
  80. data/lib/waw/routing/dsl.rb +45 -0
  81. data/lib/waw/routing/feedback.rb +23 -0
  82. data/lib/waw/routing/form_validation_feedback.rb +36 -0
  83. data/lib/waw/routing/javascript.rb +17 -0
  84. data/lib/waw/routing/redirect.rb +26 -0
  85. data/lib/waw/routing/refresh.rb +17 -0
  86. data/lib/waw/routing/routing_rule.rb +16 -0
  87. data/lib/waw/scope_utils.rb +69 -0
  88. data/lib/waw/session.rb +51 -0
  89. data/lib/waw/testing.rb +1 -0
  90. data/lib/waw/tools/mail.rb +4 -0
  91. data/lib/waw/tools/mail/mail.rb +119 -0
  92. data/lib/waw/tools/mail/mail_agent.rb +123 -0
  93. data/lib/waw/tools/mail/mailbox.rb +62 -0
  94. data/lib/waw/tools/mail/template.rb +38 -0
  95. data/lib/waw/utils/dsl_helper.rb +116 -0
  96. data/lib/waw/validation.rb +175 -0
  97. data/lib/waw/validation/and_validator.rb +27 -0
  98. data/lib/waw/validation/array_validations.rb +38 -0
  99. data/lib/waw/validation/boolean_validator.rb +32 -0
  100. data/lib/waw/validation/comparison_validations.rb +45 -0
  101. data/lib/waw/validation/date_validator.rb +31 -0
  102. data/lib/waw/validation/default_validator.rb +30 -0
  103. data/lib/waw/validation/dsl_ruby_extensions.rb +11 -0
  104. data/lib/waw/validation/errors.rb +17 -0
  105. data/lib/waw/validation/ext.rb +3 -0
  106. data/lib/waw/validation/file_validator.rb +30 -0
  107. data/lib/waw/validation/float_validator.rb +19 -0
  108. data/lib/waw/validation/helpers.rb +67 -0
  109. data/lib/waw/validation/integer_validator.rb +16 -0
  110. data/lib/waw/validation/isin_validator.rb +24 -0
  111. data/lib/waw/validation/mandatory_validator.rb +17 -0
  112. data/lib/waw/validation/missing_validator.rb +17 -0
  113. data/lib/waw/validation/not_validator.rb +20 -0
  114. data/lib/waw/validation/or_validator.rb +34 -0
  115. data/lib/waw/validation/regexp_validator.rb +29 -0
  116. data/lib/waw/validation/same_validator.rb +16 -0
  117. data/lib/waw/validation/signature.rb +157 -0
  118. data/lib/waw/validation/size_validations.rb +44 -0
  119. data/lib/waw/validation/string_validator.rb +15 -0
  120. data/lib/waw/validation/validator.rb +48 -0
  121. data/lib/waw/wawgen.rb +2 -0
  122. data/lib/waw/wawgen/create.rb +166 -0
  123. data/lib/waw/wawgen/project.rb +25 -0
  124. data/lib/waw/wspec.rb +5 -0
  125. data/lib/waw/wspec/browser.rb +240 -0
  126. data/lib/waw/wspec/dsl.rb +201 -0
  127. data/lib/waw/wspec/html_analysis.rb +136 -0
  128. data/lib/waw/wspec/html_analysis/tag.rb +56 -0
  129. data/lib/waw/wspec/runner.rb +70 -0
  130. data/lib/waw/wspec/scenario.rb +35 -0
  131. data/lib/waw/wspec/suite.rb +54 -0
  132. data/test/bricks/error_handler/config/test.cfg +2 -0
  133. data/test/bricks/error_handler/logs/webapp.log +1411 -0
  134. data/test/bricks/error_handler/test/error_handler.wspec +16 -0
  135. data/test/bricks/error_handler/waw.deploy +1 -0
  136. data/test/bricks/error_handler/waw.routing +27 -0
  137. data/test/integration/waw_create_integration_test.rb +24 -0
  138. data/test/spec/assumptions_spec.rb +30 -0
  139. data/test/spec/controllers/action_controller_spec.rb +14 -0
  140. data/test/spec/controllers/static/waw_access_spec.rb +112 -0
  141. data/test/spec/environment_utils_spec.rb +15 -0
  142. data/test/spec/ext/core/hash_spec.rb +58 -0
  143. data/test/spec/fixtures.rb +41 -0
  144. data/test/spec/fixtures/action/config/default.cfg +2 -0
  145. data/test/spec/fixtures/action/lib/action_controller_test.rb +12 -0
  146. data/test/spec/fixtures/action/waw.deploy +1 -0
  147. data/test/spec/fixtures/action/waw.routing +6 -0
  148. data/test/spec/fixtures/empty/waw.deploy +0 -0
  149. data/test/spec/fixtures/empty/waw.routing +0 -0
  150. data/test/spec/fullstate/on_class_spec.rb +59 -0
  151. data/test/spec/fullstate/on_instance_spec.rb +59 -0
  152. data/test/spec/fullstate/session_spec.rb +43 -0
  153. data/test/spec/fullstate/variable_spec.rb +55 -0
  154. data/test/spec/resource_collection_spec.rb +50 -0
  155. data/test/spec/test_all.rb +9 -0
  156. data/test/spec/tools/mail/mail_agent_spec.rb +116 -0
  157. data/test/spec/tools/mail/mail_spec.rb +56 -0
  158. data/test/spec/tools/mail/mailbox_spec.rb +57 -0
  159. data/test/spec/tools/mail/template_spec.rb +47 -0
  160. data/test/spec/validation/array_validation_spec.rb +63 -0
  161. data/test/spec/validation/array_validator_spec.rb +17 -0
  162. data/test/spec/validation/date_validation_spec.rb +35 -0
  163. data/test/spec/validation/default_validation_spec.rb +37 -0
  164. data/test/spec/validation/disjuctive_validation_spec.rb +33 -0
  165. data/test/spec/validation/errors_spec.rb +37 -0
  166. data/test/spec/validation/file_validator_spec.rb +34 -0
  167. data/test/spec/validation/mail_validation_spec.rb +51 -0
  168. data/test/spec/validation/missing_validation_spec.rb +43 -0
  169. data/test/spec/validation/same_validation_spec.rb +24 -0
  170. data/test/spec/validation/signature_intuition_spec.rb +37 -0
  171. data/test/spec/validation/signature_spec.rb +164 -0
  172. data/test/spec/validation/validation_spec.rb +28 -0
  173. data/test/spec/wspec/html_analysis/tag_spec.rb +38 -0
  174. data/test/spec/wspec/html_analysis_spec.rb +170 -0
  175. data/test/unit/test_all.rb +8 -0
  176. data/test/unit/waw/app_test.rb +126 -0
  177. data/test/unit/waw/app_test/config/commons.cfg +2 -0
  178. data/test/unit/waw/app_test/config/devel.cfg +1 -0
  179. data/test/unit/waw/config_test.rb +54 -0
  180. data/test/unit/waw/controllers/action_controller_test.rb +76 -0
  181. data/test/unit/waw/controllers/action_test.rb +35 -0
  182. data/test/unit/waw/controllers/example_action_controller_test.rb +24 -0
  183. data/test/unit/waw/controllers/multiple_action_controller_test.rb +78 -0
  184. data/test/unit/waw/controllers/static/example/css/example.css +1 -0
  185. data/test/unit/waw/controllers/static/example/index.html +1 -0
  186. data/test/unit/waw/controllers/static/example/js/example.js +1 -0
  187. data/test/unit/waw/controllers/static/example/pages/hello.wtpl +1 -0
  188. data/test/unit/waw/controllers/static/waw_access_test.rb +76 -0
  189. data/test/unit/waw/ext/rack_test.rb +74 -0
  190. data/test/unit/waw/resource_collection_test.rb +49 -0
  191. data/test/unit/waw/resources.txt +4 -0
  192. data/test/unit/waw/routing/routing_test.rb +26 -0
  193. data/test/unit/waw/utils/dsl_helper_test.rb +79 -0
  194. data/test/unit/waw/utils/dsl_helper_test_extensions1.rb +4 -0
  195. data/test/unit/waw/validation/signature_test.rb +193 -0
  196. data/test/unit/waw/validation_test.rb +319 -0
  197. data/test/unit/waw/wspec/html_analysis_test.html +81 -0
  198. data/test/unit/waw/wspec/html_analysis_test.rb +26 -0
  199. metadata +272 -0
@@ -0,0 +1,31 @@
1
+ require 'date'
2
+ module Waw
3
+ module Validation
4
+ class DateValidator < Validator
5
+
6
+ # Returns a Date object if value seems a date,
7
+ # nil otherwise
8
+ def seems_a_date?(value)
9
+ if /^\d{4}\/\d{2}\/\d{2}$/ =~ value.to_s
10
+ Date.strptime(value.to_s, "%Y/%m/%d")
11
+ elsif /^\d{2}\/\d{2}\/\d{4}$/ =~ value.to_s
12
+ Date.strptime(value.to_s, "%d/%m/%Y")
13
+ else
14
+ nil
15
+ end
16
+ rescue ArgumentError => ex
17
+ nil
18
+ end
19
+
20
+ def validate(*values)
21
+ values.all?{|val| seems_a_date?(val)}
22
+ end
23
+
24
+ def convert_and_validate(*values)
25
+ dates = values.collect{|v| seems_a_date?(v)}
26
+ dates.include?(nil) ? [false, values] : [true, dates]
27
+ end
28
+
29
+ end # class IntegerValidator
30
+ end # module Validation
31
+ end # module Waw
@@ -0,0 +1,30 @@
1
+ module Waw
2
+ module Validation
3
+ class DefaultValidator < Validator
4
+
5
+ # Creates a validator instance
6
+ def initialize(*args, &block)
7
+ error("Validator default expects one argument or a block: default(19) or default{Time.now} for example", caller)\
8
+ unless (args.size==1 and block.nil?) or (args.empty? and not(block.nil?))
9
+ @which = args.empty? ? :block : :arg
10
+ @default_value = args.empty? ? block : args[0]
11
+ end
12
+
13
+ # Always returns true
14
+ def validate(*values)
15
+ all_missing?(values)
16
+ end
17
+
18
+ # Computes the default value from a missing one
19
+ def compute_default(value)
20
+ @which == :block ? @default_value.call(value) : @default_value
21
+ end
22
+
23
+ # Converts missing values by the default one
24
+ def convert_and_validate(*values)
25
+ validate(*values) ? [true, values.collect{|v| compute_default(v)}] : [false, values]
26
+ end
27
+
28
+ end # class DefaultValidator
29
+ end # module Validation
30
+ end # module Waw
@@ -0,0 +1,11 @@
1
+ class Class
2
+ def |(validator)
3
+ ::Waw::Validation.to_validator(self) | validator
4
+ end
5
+ def &(validator)
6
+ ::Waw::Validation.to_validator(self) & validator
7
+ end
8
+ def not()
9
+ ::Waw::Validation.to_validator(self).not
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module Waw
2
+ module Validation
3
+ class Error < StandardError
4
+
5
+ # The list of failures
6
+ attr_accessor :failed
7
+
8
+ # Creates a validation error instance
9
+ def initialize(failed, msg = "Validation has failed #{failed.inspect}")
10
+ super(msg)
11
+ @failed = failed
12
+ end
13
+
14
+ end
15
+ class KO < Error; end
16
+ end
17
+ end # module Waw
@@ -0,0 +1,3 @@
1
+ # A boolean class (used as namespace only)
2
+ class Boolean
3
+ end
@@ -0,0 +1,30 @@
1
+ module Waw
2
+ module Validation
3
+ class FileValidator < Validator
4
+
5
+ def initialize(opts = {})
6
+ @options = opts
7
+ end
8
+
9
+ # Seems a valid file
10
+ def seems_a_file?(f)
11
+ return false unless File.file?(f)
12
+ return true unless @options
13
+ @options.each_pair do |key, value|
14
+ case key
15
+ when :extension
16
+ return false unless value==File.extname(f)
17
+ else
18
+ raise Waw::Error, "Unexpected FileValidator option #{key} : #{value}"
19
+ end
20
+ end
21
+ true
22
+ end
23
+
24
+ def validate(*values)
25
+ values.all?{|f| seems_a_file?(f)}
26
+ end
27
+
28
+ end # class NotValidator
29
+ end # module Validation
30
+ end # module Waw
@@ -0,0 +1,19 @@
1
+ module Waw
2
+ module Validation
3
+ class FloatValidator < ::Waw::Validation::Validator
4
+
5
+ # Regular expression we use
6
+ FLOAT_REGEXP = /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/
7
+
8
+ def validate(*values)
9
+ values.all?{|v| ::Float===v}
10
+ end
11
+
12
+ def convert_and_validate(*values)
13
+ ok = values.all?{|v| FLOAT_REGEXP =~ v.to_s}
14
+ ok ? [true, values.collect{|v| v.to_s.to_f}] : [false, values]
15
+ end
16
+
17
+ end
18
+ end # module Validation
19
+ end # module Waw
@@ -0,0 +1,67 @@
1
+ module Waw
2
+ module Validation
3
+ module Helpers
4
+
5
+ # Sends a friendly error message if something is wrong
6
+ def error(msg, the_caller)
7
+ raise ::Waw::WawError, msg, the_caller
8
+ end
9
+
10
+ # Checks if a given value is considered missing. In a web environment,
11
+ # we consider a value being missing when it is nil or an empty string
12
+ # (when stripped). All validators should use this method to share a
13
+ # common definition for 'missing'. It may be overriden, at your own
14
+ # risks however. This method always returns false when invoked on
15
+ # any value other than nil or a String.
16
+ def is_missing?(value)
17
+ value.nil? or (String===value and value.strip.empty?)
18
+ end
19
+
20
+ # Converts missing values to nil
21
+ def missings_to_nil(values)
22
+ values.collect{|v| is_missing?(v) ? nil : v}
23
+ end
24
+
25
+ # Checks if all values are missing
26
+ def all_missing?(values)
27
+ values.all?{|v| is_missing?(v)}
28
+ end
29
+
30
+ # Checks if any value is missing
31
+ def any_missing?(values)
32
+ values.any?{|v| is_missing?(v)}
33
+ end
34
+
35
+ # Checks if no value is considered missing
36
+ def no_missing?(values)
37
+ not(any_missing?(values))
38
+ end
39
+
40
+ # Yields the block inside a rescue on ArgumentError. Returns false
41
+ # if such an error has been raised
42
+ def argument_safe
43
+ yield
44
+ rescue ArgumentError
45
+ false
46
+ end
47
+
48
+ # Automatically converts specials guys as validators (regular
49
+ # expressions, some ruby classes, etc.)
50
+ def to_validator(who)
51
+ if who.is_a?(Class)
52
+ Waw::Validation.validator_for_ruby_class(who, true)
53
+ else
54
+ case who
55
+ when ::Waw::Validation::Validator
56
+ who
57
+ when Regexp
58
+ RegexpValidator.new(who, true)
59
+ else
60
+ raise "Unable to convert #{who}:#{who.class} to a validator"
61
+ end
62
+ end
63
+ end
64
+
65
+ end # module Helpers
66
+ end # module Validation
67
+ end # module Waw
@@ -0,0 +1,16 @@
1
+ module Waw
2
+ module Validation
3
+ class IntegerValidator < Validator
4
+
5
+ def validate(*values)
6
+ values.all?{|val| ::Integer===val}
7
+ end
8
+
9
+ def convert_and_validate(*values)
10
+ ok = values.all?{|v| Integer===v or (/^[+-]?\d+$/ =~ v.to_s.strip)}
11
+ ok ? [true, values.collect{|v| v.to_s.strip.to_i}] : [false, values]
12
+ end
13
+
14
+ end # class IntegerValidator
15
+ end # module Validation
16
+ end # module Waw
@@ -0,0 +1,24 @@
1
+ module Waw
2
+ module Validation
3
+ # Checks that arguments belongs to an array of allowed values provided
4
+ # at construction time.
5
+ class IsInValidator < Validator
6
+
7
+ # Creates the validator instance
8
+ def initialize(*allowed)
9
+ @allowed = (allowed.size==1 and Range===allowed[0]) ? allowed[0] : allowed
10
+ end
11
+
12
+ # Validation method
13
+ def validate(*values)
14
+ values.all?{|v| @allowed.include?(v)}
15
+ end
16
+
17
+ # Convert and validate method
18
+ def convert_and_validate(*values)
19
+ [validate(*values), values]
20
+ end
21
+
22
+ end # class IsInValidator
23
+ end # module Validation
24
+ end # module Waw
@@ -0,0 +1,17 @@
1
+ module Waw
2
+ module Validation
3
+ class MandatoryValidator < Validator
4
+
5
+ # Calls the block installed at initialization time
6
+ def validate(*values)
7
+ no_missing?(values)
8
+ end
9
+
10
+ # Converts and validate
11
+ def convert_and_validate(*values)
12
+ validate(*values) ? [true, values] : [false, values]
13
+ end
14
+
15
+ end # class MissingValidator
16
+ end # module Validation
17
+ end # module Waw
@@ -0,0 +1,17 @@
1
+ module Waw
2
+ module Validation
3
+ class MissingValidator < Validator
4
+
5
+ # Calls the block installed at initialization time
6
+ def validate(*values)
7
+ values.all?{|value| is_missing?(value)}
8
+ end
9
+
10
+ # Converts and validate
11
+ def convert_and_validate(*values)
12
+ validate(*values) ? [true, missings_to_nil(values)] : [false, values]
13
+ end
14
+
15
+ end # class MissingValidator
16
+ end # module Validation
17
+ end # module Waw
@@ -0,0 +1,20 @@
1
+ module Waw
2
+ module Validation
3
+ class NotValidator < Validator
4
+
5
+ def initialize(negated)
6
+ @negated = negated
7
+ end
8
+
9
+ def validate(*values)
10
+ not(@negated.validate(*values))
11
+ end
12
+
13
+ def convert_and_validate(*values)
14
+ ok, converted = @negated.convert_and_validate(*values)
15
+ ok ? [false, values] : [true, converted]
16
+ end
17
+
18
+ end # class NotValidator
19
+ end # module Validation
20
+ end # module Waw
@@ -0,0 +1,34 @@
1
+ module Waw
2
+ module Validation
3
+ class OrValidator < Validator
4
+
5
+ # Empty constructor that overrides the top one
6
+ def initialize(*validators)
7
+ @validators = validators
8
+ end
9
+
10
+ # Calls the block installed at initialization time
11
+ def validate(*values)
12
+ values.all?{|val| @validators.any?{|validator| validator.validate(val)}}
13
+ end
14
+
15
+ # Converts and validate
16
+ def convert_and_validate(*values)
17
+ converted = []
18
+ values.each do |value|
19
+ found = false
20
+ @validators.each do |validator|
21
+ found, val_converted = validator.convert_and_validate(value)
22
+ if found
23
+ converted << val_converted[0]
24
+ break
25
+ end
26
+ end
27
+ return [false, values] unless found
28
+ end
29
+ [true, converted]
30
+ end
31
+
32
+ end # class OrValidator
33
+ end # module Validation
34
+ end # module Waw
@@ -0,0 +1,29 @@
1
+ module Waw
2
+ module Validation
3
+ # Validator that checks that values match a given regular expression
4
+ class RegexpValidator < ::Waw::Validation::Validator
5
+
6
+ #
7
+ # Creates a validator instance.
8
+ #
9
+ # If strip is set to true, the regexp is checked against a stripped
10
+ # version of value.to_s. In this case, the conversion strips the string
11
+ # as well.
12
+ #
13
+ def initialize(regexp, strip = true)
14
+ @regexp, @strip = regexp, strip
15
+ end
16
+
17
+ # Validation method
18
+ def validate(*values)
19
+ values.all?{|v| @regexp =~ (@strip ? v.to_s.strip : v.to_s)}
20
+ end
21
+
22
+ # Converts and validate method
23
+ def convert_and_validate(*values)
24
+ validate(*values) ? [true, values.collect{|v| @strip ? v.to_s.strip : v}] : [false, values]
25
+ end
26
+
27
+ end
28
+ end # module Validation
29
+ end # module Waw
@@ -0,0 +1,16 @@
1
+ module Waw
2
+ module Validation
3
+ # Checks that arguments are all non missing and equal
4
+ class SameValidator < Validator
5
+
6
+ def validate(*values)
7
+ any_missing?(values) ? false : values.uniq.size==1
8
+ end
9
+
10
+ def convert_and_validate(*values)
11
+ [validate(*values), values]
12
+ end
13
+
14
+ end # class IntegerValidator
15
+ end # module Validation
16
+ end # module Waw
@@ -0,0 +1,157 @@
1
+ module Waw
2
+ module Validation
3
+ #
4
+ # A service or data signature, as a list of validations to be respected.
5
+ #
6
+ class Signature
7
+
8
+ # The DSL attached to signature
9
+ class DSL
10
+
11
+ # Creates a DSL instance
12
+ def initialize(signature)
13
+ @signature = signature
14
+ end
15
+
16
+ # Executes a block as this DSL
17
+ def execute(&block)
18
+ DSLHelper.new(Class => [:&, :|, :not]) do
19
+ Kernel.load(File.join(File.dirname(__FILE__), 'dsl_ruby_extensions.rb'))
20
+ self.instance_eval(&block)
21
+ end
22
+ end
23
+
24
+ # Adds a validation
25
+ def validation(args, validator, onfailure)
26
+ @signature.add_validation(args, ::Waw::Validation.to_validator(validator), onfailure)
27
+ end
28
+
29
+ # When a methos is missing
30
+ def method_missing(name, *args, &block)
31
+ Waw::Validation.send(name, *args, &block)
32
+ rescue Exception => ex
33
+ raise ex.class, ex.message, caller
34
+ end
35
+
36
+ end # class DSL
37
+
38
+ # A validation rule
39
+ class ValidationRule
40
+
41
+ # Creates a Validation instance
42
+ def initialize(args, validator, onfailure)
43
+ @args = args
44
+ @validator = validator
45
+ @onfailure = onfailure
46
+ end
47
+
48
+ # Collects the interesting parameters on a hash
49
+ def collect_on_hash(hash)
50
+ @args.collect{|arg| hash[arg]}
51
+ end
52
+
53
+ # Validates argument values given through a hash. Returns nil
54
+ # if everything is ok, the on_failure installed parameters otherwise.
55
+ def validate(hash)
56
+ @validator.validate(*collect_on_hash(hash)) ? nil : @onfailure
57
+ end
58
+
59
+ # Validates and convert a hash. Values of the hash are replaced
60
+ # by their convertions if the validation passes. In this case, a
61
+ # nil value is returned. Otherwise, the on_failure is returned
62
+ # and the hash is not changed.
63
+ def convert_and_validate(hash)
64
+ ok, values = @validator.convert_and_validate(*collect_on_hash(hash))
65
+ @args.each_with_index {|arg, i| hash[arg] = values[i]} if ok
66
+ ok ? nil : @onfailure
67
+ end
68
+
69
+ # Applies the validation and conversion rule on a hash. Returns the
70
+ # first converted (or non converted if validation fails) value.
71
+ def first_converted(hash)
72
+ ok, values = @validator.convert_and_validate(*collect_on_hash(hash))
73
+ values[0]
74
+ end
75
+
76
+ # Completes a hash of default values
77
+ def complete_defaults(hash)
78
+ ok, values = @validator.convert_and_validate(*collect_on_hash(hash))
79
+ @args.each_with_index {|arg, i| hash[arg] = values[i]}
80
+ end
81
+
82
+ end # class Validation
83
+
84
+ # Rules
85
+ attr_accessor :rules
86
+
87
+ # Creates an empty signature
88
+ def initialize(&block)
89
+ @rules = []
90
+ DSL.new(self).execute(&block) unless block.nil?
91
+ end
92
+
93
+ # Merges this signature with additional definition
94
+ def merge(&block)
95
+ signature = self.dup
96
+ DSL.new(signature).execute(&block) unless block.nil?
97
+ signature
98
+ end
99
+
100
+ # Adds a validation rule
101
+ def add_validation(args, validator, onfailure)
102
+ args = [args] if Symbol===args
103
+ @rules << ValidationRule.new(args, validator, onfailure)
104
+ end
105
+
106
+ # Validates argument values given through a hash and returns a series
107
+ # of onfailure flags.
108
+ def validate(hash)
109
+ converted, failures = hash.dup, []
110
+ failures = @rules.collect{|rule| rule.validate(converted)}.compact
111
+ failures.empty? ? [true, converted] : [false, failures]
112
+ end
113
+
114
+ # Validates argument values given through a hash and returns a series
115
+ # of onfailure flags.
116
+ def apply(hash)
117
+ raise ArgumentError, "Hash expected (did you invoked an action without a Hash?)" unless Hash===hash
118
+ converted, failures = hash.dup, []
119
+ failures = @rules.collect{|rule| rule.convert_and_validate(converted)}.compact
120
+ failures.empty? ? [true, converted] : [false, failures]
121
+ end
122
+
123
+ # Calls first_converted(hash) on the first rule. Returns nil if no rule
124
+ # has been installed. The hash is never modified by this method.
125
+ def first_converted(hash = {})
126
+ return nil if @rules.nil? or @rules.empty?
127
+ @rules[0].first_converted(hash)
128
+ end
129
+
130
+ # Checks if the signature allows passing with some values
131
+ def allows?(hash={})
132
+ apply(hash)[0]
133
+ end
134
+
135
+ # Checks if the signature blocks with some values
136
+ def blocks?(hash={})
137
+ not(allows?(hash))
138
+ end
139
+
140
+ # Computed default data for this signature
141
+ def default
142
+ defaults = {}
143
+ @rules.each {|rule| rule.complete_defaults(defaults)}
144
+ defaults
145
+ end
146
+
147
+ # Duplicates this validation
148
+ def dup
149
+ copy = Signature.new
150
+ copy.rules = self.rules.dup
151
+ copy
152
+ end
153
+
154
+ protected :rules=
155
+ end # class Signature
156
+ end # module Validation
157
+ end # module Waw