Module: JCR
- Defined in:
- lib/jcr/parts.rb,
lib/jcr/jcr.rb,
lib/jcr/parser.rb,
lib/jcr/version.rb,
lib/jcr/find_roots.rb,
lib/jcr/check_groups.rb,
lib/jcr/evaluate_rules.rb,
lib/jcr/map_rule_names.rb,
lib/jcr/process_directives.rb,
lib/jcr/jcr_validator_error.rb,
lib/jcr/evaluate_array_rules.rb,
lib/jcr/evaluate_group_rules.rb,
lib/jcr/evaluate_value_rules.rb,
lib/jcr/evaluate_member_rules.rb,
lib/jcr/evaluate_object_rules.rb
Overview
Copyright © 2017 American Registry for Internet Numbers
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Defined Under Namespace
Classes: ArrayBehavior, Context, EvalConditions, Evaluation, Failure, JcrParts, JcrValidatorError, ObjectBehavior, Parser, Root, Transformer
Constant Summary collapse
- VERSION =
"0.8.3"
Class Method Summary collapse
- .annotations_to_s(annotations) ⇒ Object
- .array_to_s(jcr, shallow = true) ⇒ Object
- .bad_value(jcr, rule_atom, expected, actual) ⇒ Object
- .breakup_message(message, line_length) ⇒ Object
- .check_array_for_group(node, mapping) ⇒ Object
- .check_groups(tree, mapping) ⇒ Object
- .check_member_for_group(node, mapping) ⇒ Object
- .check_object_for_group(node, mapping) ⇒ Object
- .check_rule_target_names(node, mapping) ⇒ Object
- .check_value_for_group(node, mapping) ⇒ Object
- .cli_eval(ctx, data, root_name, quiet) ⇒ Object
- .disallowed_group_in_array?(node, mapping) ⇒ Boolean
- .disallowed_group_in_member?(node, mapping) ⇒ Boolean
- .disallowed_group_in_object?(node, mapping) ⇒ Boolean
- .disallowed_group_in_value?(node, mapping) ⇒ Boolean
- .elide(s) ⇒ Object
- .evaluate_array(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_array_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_array_rule_ordered(jcr, rule_atom, data, econs, behavior = nil) ⇒ Object
- .evaluate_array_rule_unordered(jcr, rule_atom, data, econs, behavior = nil) ⇒ Object
- .evaluate_callback(jcr, data, econs, callback, e) ⇒ Object
- .evaluate_group(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_group_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_member(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
- .evaluate_member_rule(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
- .evaluate_not(annotations, evaluation, econs, target_annotations = nil) ⇒ Object
- .evaluate_object(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_object_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
- .evaluate_ruleset(data, ctx, root_name = nil) ⇒ Object
- .evaluate_value_rule(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
- .evaluate_values(jcr, rule_atom, data, econs) ⇒ Object
- .failure_report(ctx) ⇒ Object
- .find_first_slice(slice) ⇒ Object
- .find_roots(tree) ⇒ Object
- .find_roots_in_named(node) ⇒ Object
- .find_roots_in_unnamed(node) ⇒ Object
- .get_group(rule, econs) ⇒ Object
- .get_leaf_rule(rule, econs) ⇒ Object
- .get_name_mapping(rule_name, mapping) ⇒ Object
- .get_repetitions(rule, econs) ⇒ Object
- .get_rule_by_type(rule) ⇒ Object
- .get_rules_and_annotations(jcr) ⇒ Object
- .get_target_rule(jcr, econs) ⇒ Object
- .group_to_s(jcr, shallow = true) ⇒ Object
- .ingest_ruleset(ruleset, existing_mapping = nil, ruleset_alias = nil) ⇒ Object
- .jcr_to_s(jcr, shallow = true) ⇒ Object
- .main(my_argv = nil) ⇒ Object
- .map_rule_names(tree, ruleset_alias = nil) ⇒ Object
- .member_to_s(jcr, shallow = true) ⇒ Object
- .merge_rules(rules) ⇒ Object
- .object_to_s(jcr, shallow = true) ⇒ Object
- .parse(str) ⇒ Object
- .parse_and_transform(str) ⇒ Object
- .pop_trace_stack(econs) ⇒ Object
- .print_tree(tree) ⇒ Object
- .process_directives(ctx) ⇒ Object
- .process_import(directive, ctx) ⇒ Object
- .process_jcrversion(directive, ctx) ⇒ Object
- .process_ruleset_id(directive, ctx) ⇒ Object
- .push_trace_stack(econs, jcr) ⇒ Object
- .raise_group_error(str, node) ⇒ Object
- .raise_rule_name_missing(rule_name) ⇒ Object
- .raised_rule(jcr, rule_atom) ⇒ Object
- .repetitions_to_s(rule) ⇒ Object
- .rule_data(data = nil) ⇒ Object
- .rule_def(type, jcr) ⇒ Object
- .rule_to_s(rule, shallow = true) ⇒ Object
- .rules_to_s(rules, shallow = true) ⇒ Object
- .ruletype_to_s(rule, shallow = true) ⇒ Object
- .slice_to_s(slice) ⇒ Object
- .target_to_s(jcr) ⇒ Object
- .trace(econs, message, data = nil) ⇒ Object
- .trace_coord(econs) ⇒ Object
- .trace_def(econs, type, jcr, data) ⇒ Object
- .trace_eval(econs, message, evaluation, jcr, data, type) ⇒ Object
- .value_to_s(jcr, shallow = true) ⇒ Object
Class Method Details
.annotations_to_s(annotations) ⇒ Object
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'lib/jcr/evaluate_rules.rb', line 524 def self.annotations_to_s( annotations ) retval = "" annotations.each do |a| case when a[:unordered_annotation] retval = retval + "@{unordered}" when a[:not_annotation] retval = retval + "@{not}" when a[:root_annotation] retval = retval + "@{root}" else retval = retval + "@{ ** unknown annotation ** }" end end if annotations retval = retval + " " if retval.length != 0 return retval end |
.array_to_s(jcr, shallow = true) ⇒ Object
305 306 307 308 |
# File 'lib/jcr/evaluate_array_rules.rb', line 305 def self.array_to_s( jcr, shallow=true ) rules, annotations = get_rules_and_annotations( jcr ) return "#{annotations_to_s( annotations)}[ #{rules_to_s( rules, shallow )} ]" end |
.bad_value(jcr, rule_atom, expected, actual) ⇒ Object
404 405 406 |
# File 'lib/jcr/evaluate_value_rules.rb', line 404 def self.bad_value jcr, rule_atom, expected, actual Evaluation.new( false, "expected << #{expected} >> but got << #{actual} >> for #{raised_rule(jcr,rule_atom)}" ) end |
.breakup_message(message, line_length) ⇒ Object
177 178 179 180 181 182 183 184 |
# File 'lib/jcr/jcr.rb', line 177 def self.( , line_length ) line = .gsub(/(.{1,#{line_length}})(\s+|\Z)/, "\\1\n") lines = [] line.each_line do |l| lines << l.strip end return lines end |
.check_array_for_group(node, mapping) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/jcr/check_groups.rb', line 107 def self.check_array_for_group node, mapping if node.is_a?( Array ) node.each do |child_node| check_array_for_group( child_node, mapping ) end elsif node.is_a? Hash if node[:target_rule_name] trule = get_name_mapping(node[:target_rule_name][:rule_name], mapping) disallowed_group_in_array?(trule, mapping) elsif node[:group_rule] disallowed_group_in_array?(node[:group_rule], mapping) end end end |
.check_groups(tree, mapping) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/jcr/check_groups.rb', line 21 def self.check_groups( tree, mapping ) if tree.is_a? Array tree.each do |node| check_groups( node, mapping ) end else # is a hash if tree[:rule] check_groups( tree[:rule], mapping ) elsif tree[:primitive_rule] check_value_for_group( tree[:primitive_rule], mapping ) elsif tree[:member_rule] check_member_for_group( tree[:member_rule], mapping ) elsif tree[:array_rule] check_array_for_group( tree[:array_rule], mapping ) elsif tree[:object_rule] check_object_for_group( tree[:object_rule], mapping ) end end end |
.check_member_for_group(node, mapping) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/jcr/check_groups.rb', line 72 def self.check_member_for_group node, mapping if node.is_a? Array node = node[0] end if node[:target_rule_name] trule = get_name_mapping( node[:target_rule_name][:rule_name], mapping ) disallowed_group_in_member?( trule, mapping ) elsif node[:group_rule] disallowed_group_in_member?( node[:group_rule], mapping ) end end |
.check_object_for_group(node, mapping) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/jcr/check_groups.rb', line 140 def self.check_object_for_group node, mapping if node.is_a?( Array ) node.each do |child_node| check_object_for_group( child_node, mapping ) end elsif node.is_a? Hash if node[:target_rule_name] trule = get_name_mapping(node[:target_rule_name][:rule_name], mapping) disallowed_group_in_object?(trule, mapping) elsif node[:group_rule] disallowed_group_in_object?(node[:group_rule], mapping) end end end |
.check_rule_target_names(node, mapping) ⇒ Object
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 |
# File 'lib/jcr/map_rule_names.rb', line 45 def self.check_rule_target_names( node, mapping ) if node.is_a? Array node.each do |child_node| check_rule_target_names( child_node, mapping ) end elsif node.is_a? Hash if node[:target_rule_name] && !mapping[ node[:target_rule_name][:rule_name].to_str ] raise_rule_name_missing node[:target_rule_name][:rule_name] else if node[:rule] check_rule_target_names( node[:rule], mapping ) elsif node[:group_rule] check_rule_target_names( node[:group_rule], mapping ) elsif node[:primitive_rule] check_rule_target_names( node[:primitive_rule], mapping ) elsif node[:array_rule] check_rule_target_names( node[:array_rule], mapping ) elsif node[:object_rule] check_rule_target_names( node[:object_rule], mapping ) elsif node[:member_rule] check_rule_target_names( node[:member_rule], mapping ) end end end end |
.check_value_for_group(node, mapping) ⇒ Object
41 42 43 44 45 |
# File 'lib/jcr/check_groups.rb', line 41 def self.check_value_for_group node, mapping if node.is_a?( Hash ) && node[:group_rule] disallowed_group_in_value?( node[:group_rule], mapping ) end end |
.cli_eval(ctx, data, root_name, quiet) ⇒ Object
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
# File 'lib/jcr/jcr.rb', line 385 def self.cli_eval ctx, data, root_name, quiet ec = 2 e = ctx.evaluate( data, root_name ) if e.success unless quiet puts "Success!" end ec = 0 else unless quiet puts "Failure! Use -v for more information." ctx.failure_report.each do |line| puts line end end ec = 3 end return ec end |
.disallowed_group_in_array?(node, mapping) ⇒ Boolean
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/jcr/check_groups.rb', line 122 def self.disallowed_group_in_array? node, mapping if node.is_a? Hash node = [ node ] end node.each do |groupee| if groupee[:group_rule] disallowed_group_in_array?( groupee[:group_rule], mapping ) elsif groupee[:target_rule_name] trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping ) disallowed_group_in_array?( trule, mapping ) elsif groupee[:member_rule] raise_group_error( "groups in array rules cannot have member rules", groupee[:member_rule] ) else check_groups( groupee, mapping ) end end end |
.disallowed_group_in_member?(node, mapping) ⇒ Boolean
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/jcr/check_groups.rb', line 84 def self.disallowed_group_in_member? node, mapping if node.is_a? Hash node = [ node ] end node.each do |groupee| if groupee[:sequence_combiner] raise_group_error( 'AND (comma) operation in group rule of member rule', groupee[:sequence_combiner] ) end if groupee[:group_rule] disallowed_group_in_member?( groupee[:group_rule], mapping ) elsif groupee[:target_rule_name] trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping ) if trule[:group_rule] disallowed_group_in_member?( trule[:group_rule], mapping ) end elsif groupee[:member_rule] raise_group_error( "groups in member rules cannot have member rules", groupee[:member_rule] ) else check_groups( groupee, mapping ) end end end |
.disallowed_group_in_object?(node, mapping) ⇒ Boolean
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/jcr/check_groups.rb', line 155 def self.disallowed_group_in_object? node, mapping if node.is_a? Hash node = [ node ] end node.each do |groupee| if groupee[:group_rule] disallowed_group_in_object?( groupee[:group_rule], mapping ) elsif groupee[:target_rule_name] trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping ) disallowed_group_in_object?( trule, mapping ) elsif groupee[:array_rule] raise_group_error( "groups in object rules cannot have array rules", groupee[:member_rule] ) elsif groupee[:object_rule] raise_group_error( "groups in object rules cannot have other object rules", groupee[:member_rule] ) elsif groupee[:primitive_rule] raise_group_error( "groups in object rules cannot have value rules", groupee[:member_rule] ) else check_groups( groupee, mapping ) end end end |
.disallowed_group_in_value?(node, mapping) ⇒ Boolean
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/jcr/check_groups.rb', line 47 def self.disallowed_group_in_value? node, mapping if node.is_a? Hash node = [ node ] end node.each do |groupee| if groupee[:sequence_combiner] raise_group_error( 'AND (comma) operation in group rule of value rule', groupee[:sequence_combiner] ) end if groupee[:group_rule] disallowed_group_in_value?( groupee[:group_rule], mapping ) elsif groupee[:target_rule_name] trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping ) disallowed_group_in_value?( trule[:rule], mapping ) elsif groupee[:member_rule] raise_group_error( "groups in value rules cannot have member rules", groupee[:member_rule] ) elsif groupee[:object_rule] raise_group_error( "groups in value rules cannot have object rules", groupee[:member_rule] ) elsif groupee[:array_rule] raise_group_error( "groups in value rules cannot have array rules", groupee[:member_rule] ) elsif groupee[:primitive_rule] disallowed_group_in_value?( groupee[:primitive_rule], mapping ) end end end |
.elide(s) ⇒ Object
317 318 319 320 321 322 323 |
# File 'lib/jcr/evaluate_rules.rb', line 317 def self.elide s if s.length > 45 s = s[0..41] s = s + " ..." end return s end |
.evaluate_array(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/jcr/evaluate_array_rules.rb', line 69 def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil rules, annotations = get_rules_and_annotations( jcr ) ordered = true if behavior && behavior.is_a?( ArrayBehavior ) ordered = behavior.ordered end annotations.each do |a| if a[:unordered_annotation] ordered = false break end end # if the data is not an array return evaluate_not( annotations, Evaluation.new( false, "#{data} is not an array #{raised_rule(jcr,rule_atom)}"), econs, target_annotations ) unless data.is_a? Array # if the array is zero length and there are zero sub-rules (it is suppose to be empty) return evaluate_not( annotations, Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.empty? # if the array is not empty and there are zero sub-rules (it is suppose to be empty) return evaluate_not( annotations, Evaluation.new( false, "Non-empty array for #{raised_rule(jcr,rule_atom)}" ), econs, target_annotations ) if rules.empty? && data.length != 0 if ordered return evaluate_not( annotations, evaluate_array_rule_ordered( rules, rule_atom, data, econs, behavior ), econs, target_annotations ) else return evaluate_not( annotations, evaluate_array_rule_unordered( rules, rule_atom, data, econs, behavior ), econs, target_annotations ) end end |
.evaluate_array_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/jcr/evaluate_array_rules.rb', line 48 def self.evaluate_array_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil push_trace_stack( econs, jcr ) if behavior trace( econs, "Evaluating group in array rule starting at #{slice_to_s(jcr)} against", data ) trace_def( econs, "array group", jcr, data ) else trace( econs, "Evaluating array rule starting at #{slice_to_s(jcr)} against", data ) trace_def( econs, "array", jcr, data ) end retval = evaluate_array( jcr, rule_atom, data, econs, behavior, target_annotations ) if behavior trace_eval( econs, "Array group", retval, jcr, data, "array" ) else trace_eval( econs, "Array", retval, jcr, data, "array" ) end pop_trace_stack( econs ) return retval end |
.evaluate_array_rule_ordered(jcr, rule_atom, data, econs, behavior = nil) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/jcr/evaluate_array_rules.rb', line 109 def self.evaluate_array_rule_ordered jcr, rule_atom, data, econs, behavior = nil retval = nil behavior = ArrayBehavior.new unless behavior array_index = behavior.last_index jcr.each do |rule| # short circuit logic if rule[:choice_combiner] && retval && retval.success next elsif rule[:sequence_combiner] && retval && !retval.success break end repeat_min, repeat_max, repeat_step = get_repetitions( rule, econs ) # group rules must be evaluated differently # groups require the effects of the evaluation to be discarded if they are false # groups must also be given the entire array grule, target_annotations = get_group( rule, econs ) if grule if repeat_min == 0 retval = Evaluation.new( true, nil ) else for i in 1..repeat_min do if array_index == data.length return Evaluation.new( false, "array is not large enough for #{raised_rule(jcr,rule_atom)}" ) else group_behavior = ArrayBehavior.new( behavior ) group_behavior.last_index = array_index retval = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations ) if retval.success behavior.checked_hash.merge!( group_behavior.checked_hash ) array_index = group_behavior.last_index else break; end end end end if !retval || retval.success for i in behavior.checked_hash.length..repeat_max-1 do break if array_index == data.length group_behavior = ArrayBehavior.new( behavior ) group_behavior.last_index = array_index e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations ) if e.success behavior.checked_hash.merge!( group_behavior.checked_hash ) array_index = group_behavior.last_index else break; end end end else # else not grule (group) if repeat_min == 0 retval = Evaluation.new( true, nil ) else for i in 1..repeat_min do if array_index == data.length return Evaluation.new( false, "array is not large enough for #{raised_rule(jcr,rule_atom)}" ) else retval = evaluate_rule( rule, rule_atom, data[ array_index ], econs, nil ) break unless retval.success array_index = array_index + 1 behavior.checked_hash[ i + behavior.last_index ] = retval.success end end end if !retval || retval.success for i in behavior.checked_hash.length..repeat_max-1 do break if array_index == data.length e = evaluate_rule( rule, rule_atom, data[ array_index ], econs, nil ) break unless e.success array_index = array_index + 1 end end end # end if grule else if repeat_step && ( array_index - repeat_min ) % repeat_step != 0 retval = Evaluation.new( false, "Matches (#{array_index }) do not meat repetition step for #{repeat_max} % #{repeat_step}") end end behavior.last_index = array_index if data.length > array_index && behavior.extra_prohibited retval = Evaluation.new( false, "More items in array (#{data.length}) than specified (#{array_index}) for #{raised_rule(jcr,rule_atom)}" ) end return retval end |
.evaluate_array_rule_unordered(jcr, rule_atom, data, econs, behavior = nil) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/jcr/evaluate_array_rules.rb', line 211 def self.evaluate_array_rule_unordered jcr, rule_atom, data, econs, behavior = nil retval = nil unless behavior behavior = ArrayBehavior.new behavior.ordered = false end highest_index = 0 jcr.each do |rule| # short circuit logic if rule[:choice_combiner] && retval && retval.success next elsif rule[:sequence_combiner] && retval && !retval.success break end repeat_min, repeat_max, repeat_step = get_repetitions( rule, econs ) # group rules must be evaluated differently # groups require the effects of the evaluation to be discarded if they are false # groups must also be given the entire array grule,target_annotations = get_group(rule, econs) if grule successes = 0 for i in 0..repeat_max-1 group_behavior = ArrayBehavior.new( behavior ) group_behavior.last_index = highest_index group_behavior.ordered = false e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations ) if e.success highest_index = group_behavior.last_index behavior.checked_hash.merge!( group_behavior.checked_hash ) successes = successes + 1 else break; end end if successes == 0 && repeat_min > 0 retval = Evaluation.new( false, "array does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif successes < repeat_min retval = Evaluation.new( false, "array does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif successes > repeat_max retval = Evaluation.new( false, "array has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0 retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") else retval = Evaluation.new( true, nil ) end else # else not group rule successes = 0 for i in behavior.last_index..data.length-1 break if successes == repeat_max unless behavior.checked_hash[ i ] e = evaluate_rule( rule, rule_atom, data[ i ], econs, nil ) if e.success behavior.checked_hash[ i ] = e.success highest_index = i if i > highest_index successes = successes + 1 end end end if successes == 0 && repeat_min > 0 retval = Evaluation.new( false, "array does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif successes < repeat_min retval = Evaluation.new( false, "array does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif successes > repeat_max retval = Evaluation.new( false, "array has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0 retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") else retval = Evaluation.new( true, nil) end end # if grule else end behavior.last_index = highest_index if data.length > behavior.checked_hash.length && behavior.extra_prohibited retval = Evaluation.new( false, "More items in array #{data.length} than specified #{behavior.checked_hash.length} for #{raised_rule(jcr,rule_atom)}" ) end return retval end |
.evaluate_callback(jcr, data, econs, callback, e) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/jcr/evaluate_rules.rb', line 146 def self.evaluate_callback jcr, data, econs, callback, e retval = e c = econs.callbacks[ callback ] if e.success retval = c.jcr_callback :rule_eval_true, jcr, data else retval = c.jcr_callback :rule_eval_false, jcr, data, e end if retval.is_a? TrueClass retval = Evaluation.new( true, nil ) elsif retval.is_a? FalseClass retval = Evaluation.new( false, nil ) elsif retval.is_a? String retval = Evaluation.new( false, retval ) end trace( econs, "Callback #{callback} given evaluation of #{e.success} and returned #{retval}") return retval end |
.evaluate_group(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/jcr/evaluate_group_rules.rb', line 41 def self.evaluate_group jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil rules, annotations = get_rules_and_annotations( jcr ) retval = nil rules.each do |rule| if rule[:choice_combiner] && retval && retval.success return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit elsif rule[:sequence_combiner] && retval && !retval.success return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit end retval = evaluate_rule( rule, rule_atom, data, econs, behavior ) end return evaluate_not( annotations, retval, econs, target_annotations ) end |
.evaluate_group_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/jcr/evaluate_group_rules.rb', line 29 def self.evaluate_group_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil push_trace_stack( econs, jcr ) trace( econs, "Evaluating group rule against ", data ) trace_def( econs, "group", jcr, data ) retval = evaluate_group( jcr, rule_atom, data, econs, behavior, target_annotations ) trace_eval( econs, "Group", retval, jcr, data, "group" ) pop_trace_stack( econs ) return retval end |
.evaluate_member(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
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 |
# File 'lib/jcr/evaluate_member_rules.rb', line 40 def self.evaluate_member jcr, rule_atom, data, econs, behavior, target_annotations # unlike the other evaluate functions, here data is not just the json data. # it is an array, the first element being the member name or regex and the # second being the json data to be furthered on to other evaluation functions rules, annotations = get_rules_and_annotations( jcr ) rule = merge_rules( rules ) member_match = false if rule[:member_name] match_spec = rule[:member_name][:q_string].to_s if match_spec == data[ 0 ] member_match = true end else # must be regex regex = rule[:member_regex][:regex] if regex.is_a? Array match_spec = Regexp.new( "" ) trace( econs, "Noting empty regular expression." ) else match_spec = Regexp.new( rule[:member_regex][:regex].to_s ) end if match_spec =~ data[ 0 ] member_match = true end end if member_match e = evaluate_rule( rule, rule_atom, data[ 1 ], econs, nil, target_annotations ) e.member_found = true return evaluate_not( annotations, e, econs, target_annotations ) end return evaluate_not( annotations, Evaluation.new( false, "#{match_spec} does not match #{data[0]} for #{raised_rule( jcr, rule_atom)}" ), econs, target_annotations ) end |
.evaluate_member_rule(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/jcr/evaluate_member_rules.rb', line 28 def self.evaluate_member_rule jcr, rule_atom, data, econs, behavior, target_annotations push_trace_stack( econs, jcr ) trace( econs, "Evaluating member rule for key '#{data[0]}' starting at #{slice_to_s(jcr)} against ", data[1]) trace_def( econs, "member", jcr, data ) retval = evaluate_member( jcr, rule_atom, data, econs, behavior, target_annotations ) trace_eval( econs, "Member", retval, jcr, data, "member" ) pop_trace_stack( econs ) return retval end |
.evaluate_not(annotations, evaluation, econs, target_annotations = nil) ⇒ Object
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/jcr/evaluate_rules.rb', line 264 def self.evaluate_not annotations, evaluation, econs, target_annotations = nil is_not = false target_annotations.each do |a| if a[:not_annotation] trace( econs, "Not annotation found on reference to rule.") is_not = !is_not break end end if target_annotations annotations.each do |a| if a[:not_annotation] is_not = !is_not break end end if is_not trace( econs, "Not annotation changing result from #{evaluation.success} to #{!evaluation.success}") evaluation.success = !evaluation.success end return evaluation end |
.evaluate_object(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/jcr/evaluate_object_rules.rb', line 51 def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil rules, annotations = get_rules_and_annotations( jcr ) # if the data is not an object (Hash) return evaluate_not( annotations, Evaluation.new( false, "#{data} is not an object for #{raised_rule(jcr,rule_atom)}"), econs, target_annotations ) unless data.is_a? Hash # if the object has no members and there are zero sub-rules (it is suppose to be empty) return evaluate_not( annotations, Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.length == 0 # if the object has members and there are zero sub-rules (it is suppose to be empty) return evaluate_not( annotations, Evaluation.new( false, "Non-empty object for #{raised_rule(jcr,rule_atom)}" ), econs, target_annotations ) if rules.empty? && data.length != 0 retval = nil behavior = ObjectBehavior.new unless behavior rules.each do |rule| # short circuit logic if rule[:choice_combiner] && retval && retval.success next elsif rule[:sequence_combiner] && retval && !retval.success return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit end repeat_min, repeat_max, repeat_step = get_repetitions( rule, econs ) # Pay attention here: # Group rules need to be treated differently than other rules # Groups must be evaluated as if they are rules evaluated in # isolation until they evaluate as true. # Also, groups must be handed the entire object, not key/values # as member rules use. grule,gtarget_annotations = get_group(rule, econs) if grule successes = 0 for i in 0..repeat_max-1 group_behavior = ObjectBehavior.new group_behavior.checked_hash.merge!( behavior.checked_hash ) e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, gtarget_annotations ) if e.success behavior.checked_hash.merge!( group_behavior.checked_hash ) successes = successes + 1 else break; end end if successes == 0 && repeat_min > 0 retval = Evaluation.new( false, "object does not contain group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif successes < repeat_min retval = Evaluation.new( false, "object does not have contain necessary number of group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0 retval = Evaluation.new( false, "object matches (#{successes}) do not have contain repetition #{repeat_max} % #{repeat_step} of group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") else retval = Evaluation.new( true, nil ) end else # if not grule repeat_results = nil member_found = false # do a little lookahead for member rules defined by names # if defined by a name, and not a regex, just pluck it from the object # and short-circuit the enumeration lookahead, ltarget_annotations = get_leaf_rule( rule, econs ) lrules, lannotations = get_rules_and_annotations( lookahead[:member_rule] ) if lrules[0][:member_name] repeat_results = {} k = lrules[0][:member_name][:q_string].to_s v = data[k] if v unless behavior.checked_hash[k] e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil) behavior.checked_hash[k] = e.success member_found = true if e.member_found repeat_results[ k ] = v if e.success end else trace( econs, "No member '#{k}' found in object.") e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil) repeat_results[ nil ] = nil if e.success end else regex = lrules[0][:member_regex][:regex] trace( econs, "Scanning object for #{regex}.") i = 0 found = false repeat_results = data.select do |k,v| unless behavior.checked_hash[k] if i < repeat_max e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil) behavior.checked_hash[k] = e.success i = i + 1 if e.success found = true if e.member_found member_found = true if e.member_found e.success end end end unless found trace( econs, "No member matching #{regex} found in object.") e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil) repeat_results[ nil ] = nil if e.success end end trace( econs, "Found #{repeat_results.length} matching members repetitions in object with min #{repeat_min} and max #{repeat_max}" ) if repeat_results.length == 0 && repeat_min > 0 retval = Evaluation.new( false, "object does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_results.length < repeat_min retval = Evaluation.new( false, "object does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_results.length > repeat_max retval = Evaluation.new( false, "object has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif repeat_step && ( repeat_results.length - repeat_min ) % repeat_step != 0 retval = Evaluation.new( false, "object matches (#{repeat_results.length}) does not match repetition step of #{repeat_max} & #{repeat_step} for #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}") elsif member_found && repeat_results.length == 0 && repeat_max > 0 retval = Evaluation.new( false, "object contains #{jcr_to_s(rule)} with member name though incorrect value for #{raised_rule(jcr,rule_atom)}") else retval = Evaluation.new( true, nil) end end end # end if grule else return evaluate_not( annotations, retval, econs, target_annotations ) end |
.evaluate_object_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/jcr/evaluate_object_rules.rb', line 30 def self.evaluate_object_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil push_trace_stack( econs, jcr ) if behavior trace( econs, "Evaluating group in object rule starting at #{slice_to_s(jcr)} against", data ) trace_def( econs, "object group", jcr, data ) else trace( econs, "Evaluating object rule starting at #{slice_to_s(jcr)} against", data ) trace_def( econs, "object", jcr, data ) end retval = evaluate_object( jcr, rule_atom, data, econs, behavior, target_annotations ) if behavior trace_eval( econs, "Object group", retval, jcr, data, "object" ) else trace_eval( econs, "Object", retval, jcr, data, "object" ) end pop_trace_stack( econs ) return retval end |
.evaluate_rule(jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/jcr/evaluate_rules.rb', line 104 def self.evaluate_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil trace( econs, "Dispatching rule for #{jcr_to_s(jcr)} with data: #{data}") if jcr.is_a?( Hash ) if jcr[:rule_name] rn = slice_to_s( jcr[:rule_name] ) trace( econs, "Named Rule: #{rn}" ) end end retval = Evaluation.new( false, "failed to evaluate rule properly" ) case when behavior.is_a?( ArrayBehavior ) retval = evaluate_array_rule( jcr, rule_atom, data, econs, behavior, target_annotations ) when behavior.is_a?( ObjectBehavior ) retval = evaluate_object_rule( jcr, rule_atom, data, econs, behavior, target_annotations ) when jcr[:rule] retval = evaluate_rule( jcr[:rule], rule_atom, data, econs, behavior, target_annotations) when jcr[:target_rule_name] target, target_annotations = get_target_rule( jcr, econs ) retval = evaluate_rule( target, target, data, econs, behavior, target_annotations ) when jcr[:primitive_rule] retval = evaluate_value_rule( jcr[:primitive_rule], rule_atom, data, econs, nil, target_annotations ) when jcr[:group_rule] retval = evaluate_group_rule( jcr[:group_rule], rule_atom, data, econs, behavior, target_annotations) when jcr[:array_rule] retval = evaluate_array_rule( jcr[:array_rule], rule_atom, data, econs, behavior, target_annotations ) when jcr[:object_rule] retval = evaluate_object_rule( jcr[:object_rule], rule_atom, data, econs, behavior, target_annotations) when jcr[:member_rule] retval = evaluate_member_rule( jcr[:member_rule], rule_atom, data, econs, nil, target_annotations) else retval = Evaluation.new( true, nil ) end if jcr.is_a?( Hash ) && jcr[:rule_name] rn = jcr[:rule_name].to_s if econs.callbacks[ rn ] retval = evaluate_callback( jcr, data, econs, rn, retval ) end end return retval end |
.evaluate_ruleset(data, ctx, root_name = nil) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/jcr/jcr.rb', line 119 def self.evaluate_ruleset( data, ctx, root_name = nil ) roots = [] if root_name root_rule = ctx.mapping[root_name] raise JcrValidatorError, "No rule by the name of #{root_name} for a root rule has been found" unless root_rule root = JCR::Root.new( root_rule, root_name ) roots << root else roots = ctx.roots end raise JcrValidatorError, "No root rule defined. Specify a root rule name" if roots.empty? retval = nil roots.each do |r| pp "Evaluating Root:", rule_to_s( r.rule, false ) if ctx.trace raise JcrValidatorError, "Root rules cannot be member rules" if r.rule[:member_rule] econs = EvalConditions.new( ctx.mapping, ctx.callbacks, ctx.trace ) retval = JCR.evaluate_rule( r.rule, r.rule, data, econs ) break if retval.success # else r.failures = econs.failures ctx.failed_roots << r end ctx.failure_report = failure_report( ctx ) return retval end |
.evaluate_value_rule(jcr, rule_atom, data, econs, behavior, target_annotations) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/jcr/evaluate_value_rules.rb', line 28 def self.evaluate_value_rule jcr, rule_atom, data, econs, behavior, target_annotations push_trace_stack( econs, jcr ) trace( econs, "Evaluating value rule starting at #{slice_to_s(jcr)}" ) trace_def( econs, "value", jcr, data ) rules, annotations = get_rules_and_annotations( jcr ) retval = evaluate_not( annotations, evaluate_values( rules[0], rule_atom, data, econs ), econs, target_annotations ) trace_eval( econs, "Value", retval, jcr, data, "value") pop_trace_stack( econs ) return retval end |
.evaluate_values(jcr, rule_atom, data, econs) ⇒ Object
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/jcr/evaluate_value_rules.rb', line 42 def self.evaluate_values jcr, rule_atom, data, econs case # # any # when jcr[:any] return Evaluation.new( true, nil ) # # integers # when jcr[:integer_v] si = jcr[:integer_v].to_s if si == "integer" return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer ) end when jcr[:integer] i = jcr[:integer].to_s.to_i return bad_value( jcr, rule_atom, i, data ) unless data == i when jcr[:integer_min] != nil && jcr[:integer_max] == nil return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer ) min = jcr[:integer_min].to_s.to_i return bad_value( jcr, rule_atom, min, data ) unless data >= min when jcr[:integer_min] == nil && jcr[:integer_max] != nil return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer ) max = jcr[:integer_max].to_s.to_i return bad_value( jcr, rule_atom, max, data ) unless data <= max when jcr[:integer_min],jcr[:integer_max] return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer ) min = jcr[:integer_min].to_s.to_i return bad_value( jcr, rule_atom, min, data ) unless data >= min max = jcr[:integer_max].to_s.to_i return bad_value( jcr, rule_atom, max, data ) unless data <= max when jcr[:sized_int_v] bits = jcr[:sized_int_v][:bits].to_i return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer ) min = -(2**(bits-1)) return bad_value( jcr, rule_atom, min, data ) unless data >= min max = 2**(bits-1)-1 return bad_value( jcr, rule_atom, max, data ) unless data <= max when jcr[:sized_uint_v] bits = jcr[:sized_uint_v][:bits].to_i return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer ) min = 0 return bad_value( jcr, rule_atom, min, data ) unless data >= min max = 2**bits-1 return bad_value( jcr, rule_atom, max, data ) unless data <= max # # floats # when jcr[:float_v] sf = jcr[:float_v].to_s if sf == "float" return bad_value( jcr, rule_atom, "float", data ) unless data.is_a?( Float ) end when jcr[:float] f = jcr[:float].to_s.to_f return bad_value( jcr, rule_atom, f, data ) unless data == f when jcr[:float_min] != nil && jcr[:float_max] == nil return bad_value( jcr, rule_atom, "float", data ) unless data.is_a?( Float ) min = jcr[:float_min].to_s.to_f return bad_value( jcr, rule_atom, min, data ) unless data >= min when jcr[:float_min] == nil && jcr[:float_max] != nil return bad_value( jcr, rule_atom, "float", data ) unless data.is_a?( Float ) max = jcr[:float_max].to_s.to_f return bad_value( jcr, rule_atom, max, data ) unless data <= max when jcr[:float_min],jcr[:float_max] return bad_value( jcr, rule_atom, "float", data ) unless data.is_a?( Float ) min = jcr[:float_min].to_s.to_f return bad_value( jcr, rule_atom, min, data ) unless data >= min max = jcr[:float_max].to_s.to_f return bad_value( jcr, rule_atom, max, data ) unless data <= max when jcr[:double_v] sf = jcr[:double_v].to_s if sf == "double" return bad_value( jcr, rule_atom, "double", data ) unless data.is_a?( Float ) end # # boolean # when jcr[:true_v] return bad_value( jcr, rule_atom, "true", data ) unless data when jcr[:false_v] return bad_value( jcr, rule_atom, "false", data ) if data when jcr[:boolean_v] return bad_value( jcr, rule_atom, "boolean", data ) unless ( data.is_a?( TrueClass ) || data.is_a?( FalseClass ) ) # # strings # when jcr[:string] return bad_value( jcr, rule_atom, "string", data ) unless data.is_a? String when jcr[:q_string] s = jcr[:q_string].to_s return bad_value( jcr, rule_atom, s, data ) unless data == s # # regex # when jcr[:regex] regex = Regexp.new( jcr[:regex].to_s ) return bad_value( jcr, rule_atom, regex, data ) unless data.is_a? String return bad_value( jcr, rule_atom, regex, data ) unless data =~ regex # # ip addresses # when jcr[:ipv4] return bad_value( jcr, rule_atom, "IPv4 Address", data ) unless data.is_a? String begin ip = IPAddr.new( data ) rescue IPAddr::InvalidAddressError return bad_value( jcr, rule_atom, "IPv4 Address", data ) end return bad_value( jcr, rule_atom, "IPv4 Address", data ) unless ip.ipv4? when jcr[:ipv6] return bad_value( jcr, rule_atom, "IPv6 Address", data ) unless data.is_a? String begin ip = IPAddr.new( data ) rescue IPAddr::InvalidAddressError return bad_value( jcr, rule_atom, "IPv6 Address", data ) end return bad_value( jcr, rule_atom, "IPv6 Address", data ) unless ip.ipv6? when jcr[:ipaddr] return bad_value( jcr, rule_atom, "IP Address", data ) unless data.is_a? String begin ip = IPAddr.new( data ) rescue IPAddr::InvalidAddressError return bad_value( jcr, rule_atom, "IP Address", data ) end return bad_value( jcr, rule_atom, "IP Address", data ) unless ip.ipv6? || ip.ipv4? # # domain names # when jcr[:fqdn] return bad_value( jcr, rule_atom, "Fully Qualified Domain Name", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Fully Qualified Domain Name", data ) if data.empty? a = data.split( '.' ) a.each do |label| return bad_value( jcr, rule_atom, "Fully Qualified Domain Name", data ) if label.start_with?( '-' ) return bad_value( jcr, rule_atom, "Fully Qualified Domain Name", data ) if label.end_with?( '-' ) label.each_char do |char| unless (char >= 'a' && char <= 'z') \ || (char >= 'A' && char <= 'Z') \ || (char >= '0' && char <='9') \ || char == '-' return bad_value( jcr, rule_atom, "Fully Qualified Domain Name", data ) end end end when jcr[:idn] return bad_value( jcr, rule_atom, "Internationalized Domain Name", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Internationalized Domain Name", data ) if data.empty? a = data.split( '.' ) a.each do |label| return bad_value( jcr, rule_atom, "Internationalized Domain Name", data ) if label.start_with?( '-' ) return bad_value( jcr, rule_atom, "Internationalized Domain Name", data ) if label.end_with?( '-' ) label.each_char do |char| unless (char >= 'a' && char <= 'z') \ || (char >= 'A' && char <= 'Z') \ || (char >= '0' && char <='9') \ || char == '-' \ || char.ord > 127 return bad_value( jcr, rule_atom, "Internationalized Domain Name", data ) end end end # # uri and uri scheme # when jcr[:uri] if jcr[:uri].is_a? Hash t = jcr[:uri][:uri_scheme].to_s return bad_value( jcr, rule_atom, t, data ) unless data.is_a? String return bad_value( jcr, rule_atom, t, data ) unless data.start_with?( t ) else return bad_value( jcr, rule_atom, "URI", data ) unless data.is_a?( String ) uri = Addressable::URI.parse( data ) return bad_value( jcr, rule_atom, "URI", data ) unless uri.is_a?( Addressable::URI ) end # # phone and email value rules # when jcr[:email] return bad_value( jcr, rule_atom, "Email Address", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Email Address", data ) unless EmailAddressValidator.validate( data, true ) when jcr[:phone] return bad_value( jcr, rule_atom, "Phone Number", data ) unless data.is_a? String p = BigPhoney::PhoneNumber.new( data ) return bad_value( jcr, rule_atom, "Phone Number", data ) unless p.valid? # # hex values # when jcr[:hex] return bad_value( jcr, rule_atom, "Hex Data", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Hex Data", data ) unless data.length % 2 == 0 pad_start = false data.each_char do |char| unless (char >= '0' && char <='9') \ || (char >= 'A' && char <= 'F') \ || (char >= 'a' && char <= 'f') return bad_value( jcr, rule_atom, "Hex Data", data ) end end # # base32hex values # when jcr[:base32hex] return bad_value( jcr, rule_atom, "Base32hex Data", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Base32hex Data", data ) unless data.length % 8 == 0 pad_start = false data.each_char do |char| if char == '=' pad_start = true elsif pad_start && char != '=' return bad_value( jcr, rule_atom, "Base32hex Data", data ) else unless (char >= '0' && char <='9') \ || (char >= 'A' && char <= 'V') \ || (char >= 'a' && char <= 'v') return bad_value( jcr, rule_atom, "Base32hex Data", data ) end end end # # base32 values # when jcr[:base32] return bad_value( jcr, rule_atom, "Base 32 Data", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Base 32 Data", data ) unless data.length % 8 == 0 pad_start = false data.each_char do |char| if char == '=' pad_start = true elsif pad_start && char != '=' return bad_value( jcr, rule_atom, "Base 32 Data", data ) else unless (char >= 'a' && char <= 'z') \ || (char >= 'A' && char <= 'Z') \ || (char >= '2' && char <='7') return bad_value( jcr, rule_atom, "Base 32 Data", data ) end end end # # base64url values # when jcr[:base64url] return bad_value( jcr, rule_atom, "Base64url Data", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Base64url Data", data ) unless data.length % 4 == 0 pad_start = false data.each_char do |char| if char == '=' pad_start = true elsif pad_start && char != '=' return bad_value( jcr, rule_atom, "Base64url Data", data ) else unless (char >= 'a' && char <= 'z') \ || (char >= 'A' && char <= 'Z') \ || (char >= '0' && char <='9') \ || char == '-' || char == '_' return bad_value( jcr, rule_atom, "Base64url Data", data ) end end end # # base64 values # when jcr[:base64] return bad_value( jcr, rule_atom, "Base 64 Data", data ) unless data.is_a? String return bad_value( jcr, rule_atom, "Base 64 Data", data ) unless data.length % 4 == 0 pad_start = false data.each_char do |char| if char == '=' pad_start = true elsif pad_start && char != '=' return bad_value( jcr, rule_atom, "Base 64 Data", data ) else unless (char >= 'a' && char <= 'z') \ || (char >= 'A' && char <= 'Z') \ || (char >= '0' && char <='9') \ || char == '+' || char == '/' return bad_value( jcr, rule_atom, "Base 64 Data", data ) end end end # # time and date values # when jcr[:datetime] return bad_value( jcr, rule_atom, "Time and Date", data ) unless data.is_a? String begin Time.iso8601( data ) rescue ArgumentError return bad_value( jcr, rule_atom, "Time and Date", data ) end when jcr[:date] return bad_value( jcr, rule_atom, "Date", data ) unless data.is_a? String begin d = data + "T23:20:50.52Z" Time.iso8601( d ) rescue ArgumentError return bad_value( jcr, rule_atom, "Date", data ) end when jcr[:time] return bad_value( jcr, rule_atom, "Time", data ) unless data.is_a? String begin t = "1985-04-12T" + data + "Z" Time.iso8601( t ) rescue ArgumentError return bad_value( jcr, rule_atom, "Time", data ) end # # null # when jcr[:null] return bad_value( jcr, rule_atom, nil, data ) unless data == nil # # groups # when jcr[:group_rule] return evaluate_group_rule jcr[:group_rule], rule_atom, data, econs else raise "unknown value rule evaluation. this shouldn't happen" end return Evaluation.new( true, nil ) end |
.failure_report(ctx) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/jcr/jcr.rb', line 148 def self.failure_report ctx report = [] ctx.failed_roots.each do |failed_root| if failed_root.name report << "- Failures for root rule named '#{failed_root.name}'" else report << "- Failures for root rule at line #{failed_root.pos[0]}" end failed_root.failures.each_with_index do |failures,stack_level| if failures.length > 1 report << " - failure at rule level #{stack_level} caused by one of the following #{failures.length} reasons" else report << " - failure at rule level #{stack_level} caused by" end failures.each_with_index do |failure, index| lines = ( "<< #{failure.json_elided} >> failed rule #{failure.definition}", ctx.failure_report_line_length - 5 ) lines.each_with_index do |l,i| if i == 0 report << " - #{l}" else report << " #{l}" end end end end end return report end |
.find_first_slice(slice) ⇒ Object
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/jcr/evaluate_rules.rb', line 413 def self.find_first_slice slice if slice.is_a? Parslet::Slice return slice elsif slice.is_a?( Hash ) && !slice.empty? s = nil slice.values.each do |v| s = find_first_slice( v ) break if s end return s if s elsif slice.is_a?( Array ) && !slice.empty? s = nil slice.each do |i| s = find_first_slice( i ) break if s end return s if s end #else return nil end |
.find_roots(tree) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/jcr/find_roots.rb', line 37 def self.find_roots( tree ) roots = Array.new if tree.is_a? Hash tree = [ tree ] end tree.each do |node| if node[:rule] roots.concat( find_roots_in_named( node ) ) elsif (top_rule = get_rule_by_type( node )) roots << Root.new( node, nil, true, true ) roots.concat( find_roots_in_unnamed( top_rule ) ) end end return roots end |
.find_roots_in_named(node) ⇒ Object
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 91 92 93 94 95 96 |
# File 'lib/jcr/find_roots.rb', line 53 def self.find_roots_in_named( node ) roots = Array.new rn = node[:rule][:rule_name].to_str rule = node[:rule] ruledef = get_rule_by_type( rule ) new_root = nil # look to see if the root_annotation is in the name before assignment ( @{root} $r = ... ) if rule[:annotations] if rule[:annotations].is_a? Array rule[:annotations].each do |annotation| if annotation[:root_annotation] new_root = Root.new(node, rn) roots << new_root # root is found, now look into subrule for unnamed roots subrule = get_rule_by_type( ruledef ) roots.concat( find_roots_in_unnamed( subrule ) ) if subrule end end elsif rule[:annotations][:root_annotation] new_root = Root.new(node, rn) roots << new_root # root is found, now look into subrule for unnamed roots subrule = get_rule_by_type( ruledef ) roots.concat( find_roots_in_unnamed( subrule ) ) if subrule end end if ruledef && !new_root if ruledef.is_a? Array ruledef.each do |rdi| # if it has a @{root} annotation in the rule definition if rdi[:root_annotation] roots << Root.new(node, rn) # else look into the definition further and examine subrules elsif (subrule = get_rule_by_type(rdi)) roots.concat(find_roots_in_unnamed(subrule)) end end elsif ruledef.is_a? Hash subrule = get_rule_by_type(ruledef) roots.concat(find_roots_in_unnamed(subrule)) if subrule end end return roots end |
.find_roots_in_unnamed(node) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/jcr/find_roots.rb', line 98 def self.find_roots_in_unnamed( node ) roots = Array.new if node.is_a? Array node.each do |n| if n[:root_annotation] roots << Root.new( node ) elsif (subrule = get_rule_by_type( n ) ) roots.concat( find_roots_in_unnamed( subrule ) ) if subrule end end else subrule = get_rule_by_type( node ) roots.concat( find_roots_in_unnamed( subrule ) ) if subrule end return roots end |
.get_group(rule, econs) ⇒ Object
289 290 291 292 293 294 295 296 297 298 |
# File 'lib/jcr/evaluate_rules.rb', line 289 def self.get_group rule, econs return rule[:group_rule], nil if rule[:group_rule] #else if rule[:target_rule_name] target, target_annotations = get_target_rule( rule, econs ) return get_group( target, econs )[0], target_annotations end #else return false, nil end |
.get_leaf_rule(rule, econs) ⇒ Object
300 301 302 303 304 305 306 307 |
# File 'lib/jcr/evaluate_rules.rb', line 300 def self.get_leaf_rule rule, econs if rule[:target_rule_name ] target, target_annotations = get_target_rule( rule, econs ) return target, target_annotations end #else return rule, nil end |
.get_name_mapping(rule_name, mapping) ⇒ Object
71 72 73 74 75 |
# File 'lib/jcr/map_rule_names.rb', line 71 def self.get_name_mapping rule_name, mapping trule = mapping[ rule_name.to_str ] raise_rule_name_missing( rule_name ) unless trule return trule end |
.get_repetitions(rule, econs) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/jcr/evaluate_rules.rb', line 172 def self.get_repetitions rule, econs repeat_min = 1 repeat_max = 1 repeat_step = nil if rule[:optional] repeat_min = 0 repeat_max = 1 elsif rule[:one_or_more] repeat_min = 1 repeat_max = Float::INFINITY if rule[:repetition_step] repeat_step = rule[:repetition_step].to_s.to_i repeat_min = repeat_step end elsif rule[:zero_or_more] repeat_min = 0 repeat_max = Float::INFINITY repeat_step = rule[:repetition_step].to_s.to_i if rule[:repetition_step] elsif rule[:specific_repetition] && rule[:specific_repetition].is_a?( Parslet::Slice ) repeat_min = repeat_max = rule[:specific_repetition].to_s.to_i else o = rule[:repetition_interval] if o repeat_min = 0 repeat_max = Float::INFINITY end o = rule[:repetition_min] if o if o.is_a?( Parslet::Slice ) repeat_min = o.to_s.to_i end end o = rule[:repetition_max] if o if o.is_a?( Parslet::Slice ) repeat_max = o.to_s.to_i end end o = rule[:repetition_step] if o if o.is_a?( Parslet::Slice ) repeat_step = o.to_s.to_i end end end trace( econs, "rule repetition min = #{repeat_min} max = #{repeat_max} repetition step = #{repeat_step}" ) return repeat_min, repeat_max, repeat_step end |
.get_rule_by_type(rule) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/jcr/find_roots.rb', line 115 def self.get_rule_by_type rule retval = nil return retval unless rule.is_a? Hash case when rule[:array_rule] retval = rule[:array_rule] when rule[:object_rule] retval = rule[:object_rule] when rule[:member_rule] retval = rule[:member_rule] when rule[:primitive_rule] retval = rule[:primitive_rule] when rule[:group_rule] retval = rule[:group_rule] end return retval end |
.get_rules_and_annotations(jcr) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/jcr/evaluate_rules.rb', line 223 def self.get_rules_and_annotations jcr rules = [] annotations = [] if jcr.is_a?( Hash ) jcr = [ jcr ] end if jcr.is_a? Array i = 0 jcr.each do |sub| case when sub[:unordered_annotation] annotations << sub i = i + 1 when sub[:not_annotation] annotations << sub i = i + 1 when sub[:root_annotation] annotations << sub i = i + 1 when sub[:primitive_rule],sub[:object_rule],sub[:group_rule],sub[:array_rule],sub[:target_rule_name] break end end rules = jcr[i,jcr.length] end return rules, annotations end |
.get_target_rule(jcr, econs) ⇒ Object
165 166 167 168 169 170 |
# File 'lib/jcr/evaluate_rules.rb', line 165 def self.get_target_rule jcr, econs target = econs.mapping[ jcr[:target_rule_name][:rule_name].to_s ] raise "Target rule not in mapping. This should have been checked earlier." unless target trace( econs, "Referencing target rule #{slice_to_s(target)} from #{slice_to_s( jcr[:target_rule_name][:rule_name] )}" ) return target,jcr[:target_rule_name][:annotations] end |
.group_to_s(jcr, shallow = true) ⇒ Object
59 60 61 62 |
# File 'lib/jcr/evaluate_group_rules.rb', line 59 def self.group_to_s( jcr, shallow=true) rules, annotations = get_rules_and_annotations( jcr ) return "#{annotations_to_s( annotations)}( #{rules_to_s(rules,shallow)} )" end |
.ingest_ruleset(ruleset, existing_mapping = nil, ruleset_alias = nil) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/jcr/jcr.rb', line 101 def self.ingest_ruleset( ruleset, existing_mapping = nil, ruleset_alias=nil ) tree = JCR.parse( ruleset ) mapping = JCR.map_rule_names( tree, ruleset_alias ) combined_mapping = {} combined_mapping.merge!( existing_mapping ) if existing_mapping combined_mapping.merge!( mapping ) JCR.check_rule_target_names( tree, combined_mapping ) JCR.check_groups( tree, combined_mapping ) roots = JCR.find_roots( tree ) ctx = Context.new ctx.tree = tree ctx.mapping = mapping ctx.callbacks = {} ctx.roots = roots JCR.process_directives( ctx ) return ctx end |
.jcr_to_s(jcr, shallow = true) ⇒ Object
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'lib/jcr/evaluate_rules.rb', line 450 def self.jcr_to_s( jcr, shallow=true ) if jcr.is_a? Array retval = "" jcr.each_with_index do |item,idx| if idx > 1 retval = retval + " , " end retval = retval + jcr_to_s( item, shallow ) end elsif jcr.is_a? Parslet::Slice retval = slice_to_s( jcr ) else if jcr[:q_string] retval = value_to_s( jcr ) else retval = rule_to_s( jcr, shallow ) end end return "<< " + retval + " >>" end |
.main(my_argv = nil) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/jcr/jcr.rb', line 186 def self.main my_argv=nil my_argv = ARGV unless my_argv = {} opt_parser = OptionParser.new do |opt| opt. = "Usage: jcr [OPTIONS] [JSON_FILES]" opt.separator "" opt.separator "Evaluates JSON against JSON Content Rules (JCR)." opt.separator "" opt.separator "If -J is not specified, JSON_FILES is used." opt.separator "If JSON_FILES is not specified, standard input (STDIN) is used." opt.separator "" opt.separator "Use -v to see results, otherwise check the exit code." opt.separator "" opt.separator "Options" opt.on("-r FILE","file containing ruleset") do |ruleset| if [:ruleset] puts "A ruleset has already been specified. Use -h for help.", "" return 2 end [:ruleset] = File.open( ruleset ).read end opt.on("-R STRING","string containing ruleset. Should probably be quoted") do |ruleset| if [:ruleset] puts "A ruleset has already been specified. Use -h for help.", "" return 2 end [:ruleset] = ruleset end opt.on("--test-jcr", "parse and test the JCR only") do |testjcr| [:testjcr] = true end opt.on("--process-parts [DIRECTORY]", "creates smaller files for specification writing" ) do |directory| [:process_parts] = true [:process_parts_directory] = directory end opt.on("-S STRING","name of root rule. All roots will be tried if none is specified") do |root_name| if [:root_name] puts "A root has already been specified. Use -h for help.", "" return 2 end [:root_name] = root_name end opt.on("-o FILE","file containing overide ruleset (option can be repeated)") do |ruleset| unless [:overrides] [:overrides] = Array.new end [:overrides] << File.open( ruleset ).read end opt.on("-O STRING","string containing overide rule (option can be repeated)") do |rule| unless [:overrides] [:overrides] = Array.new end [:overrides] << rule end opt.on("-J STRING","string containing JSON to evaluate. Should probably be quoted") do |json| if [:json] puts "JSON has already been specified. Use -h for help.", "" return 2 end [:json] = json end opt.on("-v","verbose") do |verbose| [:verbose] = true end opt.on("-q","quiet") do |quiet| [:quiet] = true end opt.on("-h","display help") do |help| [:help] = true end opt.separator "" opt.separator "Return codes:" opt.separator " 0 = success" opt.separator " 1 = bad JCR parsing or other bad condition" opt.separator " 2 = invalid option or bad use of command" opt.separator " 3 = unsuccessful evaluation of JSON" opt.separator "" opt.separator "JCR Version " + JCR::VERSION end begin opt_parser.parse! my_argv rescue OptionParser::InvalidOption => e puts "Unable to interpret command or options" puts e. puts "", "Use -h for help" return 2 end if [:help] puts "HELP","----","" puts opt_parser return 2 elsif ![:ruleset] puts "No ruleset passed! Use -R or -r options.", "" puts "Use -h for help" return 2 else begin ctx = Context.new( [:ruleset], [:verbose] ) if [:overrides] [:overrides].each do |ov| ctx.override!( ov ) end end if [:verbose] pp "Ruleset Parse Tree", ctx.tree puts "Ruleset Map" ctx.mapping.each do |name,rule| puts "Parsed Rule: #{name}" puts rule_to_s( rule, false ) puts "Parsed Rule Structure: #{name}" pp rule end end if [:process_parts] parts = JCR::JcrParts.new parts.process_ruleset( [:ruleset], [:process_parts_directory] ) if [:overrides ] [:overrides].each do |ov| parts = JCR::JcrParts.new parts.process_ruleset( ov, [:process_parts_directory] ) end end end if [:testjcr] #we got this far which means the JCR was already parsed without #issue. therefore return 0 return 0 elsif [:json] data = JSON.parse( [:json] ) ec = cli_eval( ctx, data, [:root_name], [:quiet] ) return ec elsif $stdin.tty? ec = 0 if my_argv.empty? ec = 2 else my_argv.each do |fn| data = JSON.parse( File.open( fn ).read ) tec = cli_eval( ctx, data, [:root_name], [:quiet] ) ec = tec if tec != 0 #record error but don't let non-error overwrite error end end return ec else lines = "" ec = 0 ARGF.each do |line| lines = lines + line if ARGF.eof? data = JSON.parse( lines ) tec = cli_eval( ctx, data, [:root_name], [:quiet] ) ec = tec if tec != 0 #record error but don't let non-error overwrite error lines = "" end end return ec end rescue JCR::JcrValidatorError => jcr_error puts jcr_error. return 1 rescue Parslet::ParseFailed => failure puts failure.parse_failure_cause.ascii_tree unless [:quiet] return 1 rescue JSON::ParserError => parser_error unless [:quiet] puts "Unable to parse JSON" puts parser_error..inspect end return 3 end end end |
.map_rule_names(tree, ruleset_alias = nil) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/jcr/map_rule_names.rb', line 20 def self.map_rule_names( tree, ruleset_alias = nil ) prefix = "" if ruleset_alias prefix = ruleset_alias unless prefix.end_with?( "." ) prefix = prefix + "." end end rule_name_maping = Hash.new if tree.is_a? Hash tree = [ tree ] end tree.each do |node| if node[:rule] rn = prefix + node[:rule][:rule_name].to_str if rule_name_maping[ rn ] raise JCR::JcrValidatorError, "Rule #{rn} already exists and is defined more than once" else rule_name_maping[ rn ] = node[:rule] end end end return rule_name_maping end |
.member_to_s(jcr, shallow = true) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/jcr/evaluate_member_rules.rb', line 82 def self.member_to_s( jcr, shallow=true ) rules, annotations = get_rules_and_annotations( jcr ) retval = "" rule = merge_rules( rules ) case when rule[:member_name] retval = %Q|"#{rule[:member_name][:q_string].to_s}"| when rule[:member_regex] retval = "/#{rule[:member_regex][:regex].to_s}/" else retval = "** unknown member rule **" end retval = retval + " : " + rule_to_s( rule, shallow ) return annotations_to_s( annotations ) + retval end |
.merge_rules(rules) ⇒ Object
254 255 256 257 258 259 260 261 262 |
# File 'lib/jcr/evaluate_rules.rb', line 254 def self.merge_rules rules new_rule = Hash.new rules.each do |rule| new_rule.merge!(rule) do |key,oldval,newval| raise "error: conflict in merge of #{rule} with #{new_rule}" end end return new_rule end |
.object_to_s(jcr, shallow = true) ⇒ Object
192 193 194 195 |
# File 'lib/jcr/evaluate_object_rules.rb', line 192 def self.object_to_s( jcr, shallow=true ) rules, annotations = get_rules_and_annotations( jcr ) return "#{annotations_to_s( annotations)}{ #{rules_to_s(rules,shallow)} }" end |
.parse(str) ⇒ Object
462 463 464 465 466 467 |
# File 'lib/jcr/parser.rb', line 462 def self.parse(str) parser = Parser.new parser.parse(str) end |
.parse_and_transform(str) ⇒ Object
469 470 471 472 473 474 475 476 477 478 479 |
# File 'lib/jcr/parser.rb', line 469 def self.parse_and_transform(str) # provided for the fun of it parser = Parser.new tree = parser.parse(str) pp tree transformer = Transformer.new transformer.apply( tree ) end |
.pop_trace_stack(econs) ⇒ Object
313 314 315 |
# File 'lib/jcr/evaluate_rules.rb', line 313 def self.pop_trace_stack econs econs.trace_stack.pop end |
.print_tree(tree) ⇒ Object
481 482 483 484 485 486 487 |
# File 'lib/jcr/parser.rb', line 481 def self.print_tree( tree ) tree.each do |node| puts "named rule: " + node[:rule][:rule_name] if node[:rule] end end |
.process_directives(ctx) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/jcr/process_directives.rb', line 25 def self.process_directives( ctx ) tree = ctx.tree if tree.is_a? Hash tree = [ tree ] end tree.each do |node| if node[:directive] d = node[:directive] case when d[:ruleset_id_d] process_ruleset_id( d[:ruleset_id_d], ctx ) when d[:import_d] process_import( d[:import_d], ctx ) when d[:jcr_version_d] process_jcrversion( d[:jcr_version_d], ctx ) end end end end |
.process_import(directive, ctx) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/jcr/process_directives.rb', line 62 def self.process_import( directive, ctx ) ruleset_id = directive[:ruleset_id].to_str ruleset_alias = directive[:ruleset_id_alias].to_str u = ctx.map_ruleset_alias( ruleset_alias, ruleset_id ) uri = URI.parse( u ) ruleset = nil case uri.scheme when "http","https" response = Net::HTTP.get_response uri ruleset = response.body else ruleset = File.open( uri.path ) end import_ctx = JCR.ingest_ruleset( ruleset, nil, ruleset_alias ) ctx.mapping.merge!( import_ctx.mapping ) ctx.roots.concat( import_ctx.roots ) end |
.process_jcrversion(directive, ctx) ⇒ Object
51 52 53 54 55 56 57 58 59 60 |
# File 'lib/jcr/process_directives.rb', line 51 def self.process_jcrversion( directive, ctx ) major = directive[:major_version].to_str.to_i minor = directive[:minor_version].to_str.to_i if major != 0 raise "jcr version #{major}.#{minor} is incompatible with 0.7" end if minor != 7 raise "jcr version #{major}.#{minor} is incompatible with 0.7" end end |
.process_ruleset_id(directive, ctx) ⇒ Object
47 48 49 |
# File 'lib/jcr/process_directives.rb', line 47 def self.process_ruleset_id( directive, ctx ) ctx.id = directive[:ruleset_id].to_str end |
.push_trace_stack(econs, jcr) ⇒ Object
309 310 311 |
# File 'lib/jcr/evaluate_rules.rb', line 309 def self.push_trace_stack econs, jcr econs.trace_stack.push( find_first_slice( jcr ) ) end |
.raise_group_error(str, node) ⇒ Object
177 178 179 180 181 182 183 184 185 |
# File 'lib/jcr/check_groups.rb', line 177 def self.raise_group_error str, node if node.is_a?( Parslet::Slice ) pos = node.line_and_column name = node.to_str raise JCR::JcrValidatorError, "group rule error at line " + pos[0].to_s + " column " + pos[1].to_s + " name '" + name + "' :" + str else raise JCR::JcrValidatorError, "group rule error with '" + node.to_s + "' :" + str end end |
.raise_rule_name_missing(rule_name) ⇒ Object
77 78 79 80 81 82 |
# File 'lib/jcr/map_rule_names.rb', line 77 def self.raise_rule_name_missing rule_name pos = rule_name.line_and_column name = rule_name.to_str raise JCR::JcrValidatorError, "rule '" + name + "' at line " + pos[0].to_s + " column " + pos[1].to_s + " does not exist" end |
.raised_rule(jcr, rule_atom) ⇒ Object
446 447 448 |
# File 'lib/jcr/evaluate_rules.rb', line 446 def self.raised_rule jcr, rule_atom " rule at #{slice_to_s(jcr)} #{jcr_to_s(jcr)} from rule at #{slice_to_s(rule_atom)}" end |
.repetitions_to_s(rule) ⇒ Object
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 |
# File 'lib/jcr/evaluate_rules.rb', line 546 def self.repetitions_to_s rule retval = "" if rule[:optional] retval = "?" elsif rule[:one_or_more] retval = "+" if rule[:repetition_step] retval = "%" + rule[:repetition_step].to_s end elsif rule[:zero_or_more] retval = "*" retval = retval + "%" + rule[:repetition_step].to_s if rule[:repetition_step] elsif rule[:specific_repetition] && rule[:specific_repetition].is_a?( Parslet::Slice ) retval = "*" + rule[:specific_repetition].to_s else if rule[:repetition_interval] min = "0" max = "INF" o = rule[:repetition_min] if o if o.is_a?(Parslet::Slice) min = o.to_s end end o = rule[:repetition_max] if o if o.is_a?(Parslet::Slice) max = o.to_s end end retval = "*"+min+".."+max end o = rule[:repetition_step] if o if o.is_a?( Parslet::Slice ) retval = retval + "%" + o.to_s end end end retval = " " + retval if retval.length != 0 return retval end |
.rule_data(data = nil) ⇒ Object
325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/jcr/evaluate_rules.rb', line 325 def self.rule_data data=nil if data if data.is_a? String s = '"' + data + '"' else s = data.pretty_print_inspect end return elide(s) end #else return nil end |
.rule_def(type, jcr) ⇒ Object
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
# File 'lib/jcr/evaluate_rules.rb', line 354 def self.rule_def type, jcr s = "" case type when "value" s = elide(value_to_s(jcr)) when "member" s = elide(member_to_s(jcr)) when "object" s = elide(object_to_s(jcr)) when "object group" s = elide(group_to_s(jcr)) when "array" s = elide(array_to_s(jcr)) when "array group" s = elide(array_to_s(jcr)) when "group" s = elide(group_to_s(jcr)) else s = "** unknown rule **" end return "#{type} definition << #{s} >>" end |
.rule_to_s(rule, shallow = true) ⇒ Object
471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/jcr/evaluate_rules.rb', line 471 def self.rule_to_s( rule, shallow=true) if rule[:rule_name] if rule[:primitive_rule] retval = "$#{rule[:rule_name].to_s} =: #{ruletype_to_s( rule, shallow )}" else retval = "$#{rule[:rule_name].to_s} = #{ruletype_to_s( rule, shallow )}" end else retval = ruletype_to_s( rule, shallow ) end return retval end |
.rules_to_s(rules, shallow = true) ⇒ Object
509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/jcr/evaluate_rules.rb', line 509 def self.rules_to_s( rules, shallow=true) retval = "" rules.each do |rule| if rule[:rule_name] next elsif rule[:choice_combiner] retval = retval + " | " elsif rule[:sequence_combiner] retval = retval + " , " end retval = retval + rule_to_s( rule, shallow ) + repetitions_to_s( rule ) end return retval end |
.ruletype_to_s(rule, shallow = true) ⇒ Object
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
# File 'lib/jcr/evaluate_rules.rb', line 484 def self.ruletype_to_s( rule, shallow=true ) if rule[:primitive_rule] retval = value_to_s( rule[:primitive_rule] ) elsif rule[:member_rule] retval = member_to_s( rule[:member_rule], shallow ) elsif rule[:object_rule] retval = object_to_s( rule[:object_rule], shallow ) elsif rule[:array_rule] retval = array_to_s( rule[:array_rule], shallow ) elsif rule[:group_rule] retval = group_to_s( rule[:group_rule], shallow ) elsif rule[:target_rule_name] retval = target_to_s( rule[:target_rule_name] ) elsif rule[:rule_name] retval = "rule: #{rule[:rule_name].to_s}" elsif rule[:rule] retval = rule_to_s( rule[:rule], shallow ) else retval = "** unknown rule definition ** #{rule}" end return retval end |
.slice_to_s(slice) ⇒ Object
435 436 437 438 439 440 441 442 443 444 |
# File 'lib/jcr/evaluate_rules.rb', line 435 def self.slice_to_s slice s = find_first_slice( slice ) if s.is_a? Parslet::Slice pos = s.line_and_column retval = "'#{s.inspect}' ( line #{pos[0]} column #{pos[1]} )" else retval = slice.to_s end retval end |
.target_to_s(jcr) ⇒ Object
542 543 544 |
# File 'lib/jcr/evaluate_rules.rb', line 542 def self.target_to_s( jcr ) return annotations_to_s( jcr[:annotations] ) + "$" + jcr[:rule_name].to_s end |
.trace(econs, message, data = nil) ⇒ Object
338 339 340 341 342 343 344 345 346 |
# File 'lib/jcr/evaluate_rules.rb', line 338 def self.trace econs, , data = nil if econs.trace if data = "#{} data: #{rule_data( data )}" end last = econs.trace_stack.last puts "[ depth=#{econs.trace_stack.length}:#{trace_coord(econs)} ] #{}" end end |
.trace_coord(econs) ⇒ Object
348 349 350 351 352 |
# File 'lib/jcr/evaluate_rules.rb', line 348 def self.trace_coord econs last = econs.trace_stack.last pos = "#{last.line_and_column}" if last return "pos=#{pos}" end |
.trace_def(econs, type, jcr, data) ⇒ Object
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/jcr/evaluate_rules.rb', line 377 def self.trace_def econs, type, jcr, data if econs.trace s = "" case type when "value" s = elide( value_to_s( jcr ) ) when "member" s = elide( member_to_s( jcr ) ) when "object" s = elide( object_to_s( jcr ) ) when "object group" s = elide( group_to_s( jcr ) ) when "array" s = elide( array_to_s( jcr ) ) when "array group" s = elide( array_to_s( jcr ) ) when "group" s = elide( group_to_s( jcr ) ) else s = "** unknown rule **" end trace( econs, rule_def( type, jcr ) ) end end |
.trace_eval(econs, message, evaluation, jcr, data, type) ⇒ Object
402 403 404 405 406 407 408 409 410 411 |
# File 'lib/jcr/evaluate_rules.rb', line 402 def self.trace_eval econs, , evaluation, jcr, data, type if evaluation.success econs.report_success trace( econs, "#{} evaluation is true" ) else failure = Failure.new( data, jcr, type, evaluation, econs.trace_stack.length ) econs.report_failure( failure ) trace( econs, "#{} evaluation failed: #{evaluation.reason}") end end |
.value_to_s(jcr, shallow = true) ⇒ Object
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
# File 'lib/jcr/evaluate_value_rules.rb', line 408 def self.value_to_s( jcr, shallow=true ) rules, annotations = get_rules_and_annotations( jcr ) rule = rules[ 0 ] retval = "" case when rule[:any] retval = "any" when rule[:integer_v] retval = rule[:integer_v].to_s when rule[:integer] retval = rule[:integer].to_s.to_i when rule[:integer_min],rule[:integer_max] min = "-INF" max = "INF" min = rule[:integer_min].to_s.to_i if rule[:integer_min] max = rule[:integer_max].to_s.to_i if rule[:integer_max] retval = "#{min}..#{max}" when rule[:sized_int_v] retval = "int" + rule[:sized_int_v][:bits].to_s when rule[:sized_uint_v] retval = "uint" + rule[:sized_uint_v][:bits].to_s when rule[:double_v] retval = rule[:double_v].to_s when rule[:float_v] retval = rule[:float_v].to_s when rule[:float] retval = rule[:float].to_s.to_f when rule[:float_min],rule[:float_max] min = "-INF" max = "INF" min = rule[:float_min].to_s.to_f if rule[:float_min] max = rule[:float_max].to_s.to_f if rule[:float_max] retval = "#{min}..#{max}" when rule[:true_v] retval = "true" when rule[:false_v] retval = "false" when rule[:boolean_v] retval = "boolean" when rule[:string] retval = "string" when rule[:q_string] retval = %Q|"#{rule[:q_string].to_s}"| when rule[:regex] retval = "/#{rule[:regex].to_s}/" when rule[:ipv4] retval = "ipv4" when rule[:ipv6] retval = "ipv6" when rule[:fqdn] retval = "fqdn" when rule[:idn] retval = "idn" when rule[:uri] if rule[:uri].is_a? Hash retval = "uri..#{rule[:uri][:uri_scheme].to_s}" else retval = "uri" end when rule[:email] retval = "email" when rule[:phone] retval = "phone" when rule[:hex] retval = "hex" when rule[:base32hex] retval = "base32hex" when rule[:base64url] retval = "base64url" when rule[:base64] retval = "base64" when rule[:datetime] retval = "datetime" when rule[:date] retval = "date" when rule[:time] retval = "time" when rule[:null] retval = "null" when rule[:group_rule] retval = group_to_s( rule[:group_rule], shallow ) else retval = "** unknown value rule **" end return annotations_to_s( annotations ) + retval.to_s end |