j2119 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/NOTICE.txt +3 -0
- data/README.md +97 -0
- data/Rakefile +10 -0
- data/j2119.gemspec +15 -0
- data/lib/j2119/allowed_fields.rb +35 -0
- data/lib/j2119/assigner.rb +223 -0
- data/lib/j2119/conditional.rb +40 -0
- data/lib/j2119/constraints.rb +312 -0
- data/lib/j2119/deduce.rb +39 -0
- data/lib/j2119/json_path_checker.rb +58 -0
- data/lib/j2119/matcher.rb +233 -0
- data/lib/j2119/node_validator.rb +78 -0
- data/lib/j2119/oxford.rb +67 -0
- data/lib/j2119/parser.rb +101 -0
- data/lib/j2119/role_constraints.rb +32 -0
- data/lib/j2119/role_finder.rb +143 -0
- data/lib/j2119.rb +77 -0
- metadata +77 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
module J2119
|
15
|
+
|
16
|
+
class NodeValidator
|
17
|
+
|
18
|
+
def initialize(parser)
|
19
|
+
@parser = parser
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate_node(node, path, roles, problems)
|
23
|
+
|
24
|
+
if !node.is_a?(Hash)
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
# may have more roles based on field presence/value etc
|
29
|
+
@parser.find_more_roles(node, roles)
|
30
|
+
|
31
|
+
# constraints are attached per-role
|
32
|
+
# TODO - look through the constraints and if there is a
|
33
|
+
# "Field should not exist" constraint, then disable
|
34
|
+
# type and value checking constraints
|
35
|
+
#
|
36
|
+
roles.each do |role|
|
37
|
+
@parser.get_constraints(role).each do |constraint|
|
38
|
+
if constraint.applies(node, roles)
|
39
|
+
constraint.check(node, path, problems)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# for each field
|
45
|
+
node.each do |name, val|
|
46
|
+
|
47
|
+
if !@parser.field_allowed?(roles, name)
|
48
|
+
problems << "Field \"#{name}\" not allowed in #{path}"
|
49
|
+
end
|
50
|
+
|
51
|
+
# only recurse into children if they have roles
|
52
|
+
child_roles = @parser.find_child_roles(roles, name)
|
53
|
+
if !child_roles.empty?
|
54
|
+
validate_node(val, "#{path}.#{name}", child_roles, problems)
|
55
|
+
end
|
56
|
+
|
57
|
+
# find inheritance-based roles for that field
|
58
|
+
grandchild_roles = @parser.find_grandchild_roles(roles, name)
|
59
|
+
|
60
|
+
# recurse into grandkids
|
61
|
+
if val.is_a? Hash
|
62
|
+
val.each do |child_name, child_val|
|
63
|
+
validate_node(child_val, "#{path}.#{name}.#{child_name}",
|
64
|
+
grandchild_roles.clone, problems)
|
65
|
+
end
|
66
|
+
elsif val.is_a? Array
|
67
|
+
i = 0
|
68
|
+
val.each do |member|
|
69
|
+
validate_node(member, "#{path}.#{name}[#{i}]",
|
70
|
+
grandchild_roles.clone, problems)
|
71
|
+
i += 1
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/j2119/oxford.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
module J2119
|
15
|
+
|
16
|
+
# We have to recognize lots of lists like so:
|
17
|
+
# X
|
18
|
+
# X or X
|
19
|
+
# X, X, or X
|
20
|
+
# Examples:
|
21
|
+
# one of "Foo", "Bar", or "Baz"
|
22
|
+
# a Token1, a Token2, or a Token3
|
23
|
+
class Oxford
|
24
|
+
BASIC = "(?<CAPTURE>X((((,\\s+X)+,)?)?\\s+or\\s+X)?)"
|
25
|
+
|
26
|
+
def self.re(particle, opts = {})
|
27
|
+
has_capture, inter, has_connector, last = BASIC.split 'X'
|
28
|
+
has_connector.gsub!('or', opts[:connector]) if opts[:connector]
|
29
|
+
if opts[:use_article]
|
30
|
+
particle = "an?\\s+(#{particle})"
|
31
|
+
else
|
32
|
+
particle = "(#{particle})"
|
33
|
+
end
|
34
|
+
if opts[:capture_name]
|
35
|
+
has_capture.gsub!('CAPTURE', opts[:capture_name])
|
36
|
+
else
|
37
|
+
has_capture.gsub!('?<CAPTURE>', '')
|
38
|
+
end
|
39
|
+
[ has_capture, inter, has_connector, last].join(particle)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.break_string_list list
|
43
|
+
pieces = []
|
44
|
+
re = Regexp.compile "^[^\"]*\"([^\"]*)\""
|
45
|
+
while list =~ re
|
46
|
+
pieces << $1
|
47
|
+
list = $'
|
48
|
+
end
|
49
|
+
pieces
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.break_role_list(matcher, list)
|
53
|
+
pieces = []
|
54
|
+
re = Regexp.compile "^an?\\s+(#{matcher.role_matcher})(,\\s+)?"
|
55
|
+
while list =~ re
|
56
|
+
pieces << $1
|
57
|
+
list = $'
|
58
|
+
end
|
59
|
+
if list =~ /^\s*(and|or)\s+an?\s+(#{matcher.role_matcher})/
|
60
|
+
pieces << $2
|
61
|
+
end
|
62
|
+
pieces
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
data/lib/j2119/parser.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
module J2119
|
15
|
+
|
16
|
+
class Parser
|
17
|
+
|
18
|
+
ROOT = Regexp.new('This\s+document\s+specifies\s+' +
|
19
|
+
'a\s+JSON\s+object\s+called\s+an?\s+"([^"]+)"\.')
|
20
|
+
|
21
|
+
attr_reader :root
|
22
|
+
|
23
|
+
# for debugging
|
24
|
+
attr_reader :finder
|
25
|
+
|
26
|
+
def initialize(j2119_file)
|
27
|
+
|
28
|
+
have_root = false
|
29
|
+
@failed = false
|
30
|
+
@constraints = RoleConstraints.new
|
31
|
+
@finder = RoleFinder.new
|
32
|
+
@allowed_fields = AllowedFields.new
|
33
|
+
|
34
|
+
j2119_file.each_line do |line|
|
35
|
+
if line =~ ROOT
|
36
|
+
if have_root
|
37
|
+
fail "Only one root declaration"
|
38
|
+
else
|
39
|
+
@root = $1
|
40
|
+
@matcher = Matcher.new(root)
|
41
|
+
@assigner =
|
42
|
+
Assigner.new(@constraints, @finder, @matcher, @allowed_fields)
|
43
|
+
have_root = true
|
44
|
+
end
|
45
|
+
else
|
46
|
+
if !have_root
|
47
|
+
fail "Root declaration must come first"
|
48
|
+
else
|
49
|
+
proc_line(line)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if @failed
|
54
|
+
raise "Could not create parser"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def proc_line(line)
|
59
|
+
if @matcher.is_constraint_line(line)
|
60
|
+
@assigner.assign_constraints @matcher.build_constraint(line)
|
61
|
+
elsif @matcher.is_only_one_match_line(line)
|
62
|
+
@assigner.assign_only_one_of(@matcher.build_only_one(line))
|
63
|
+
elsif line =~ /^Each of a/
|
64
|
+
eaches_line = @matcher.eachof_match.match(line)
|
65
|
+
eaches = Oxford.break_role_list(@matcher, eaches_line['each_of'])
|
66
|
+
eaches.each do |each|
|
67
|
+
proc_line("A #{each} #{eaches_line['trailer']}")
|
68
|
+
end
|
69
|
+
elsif @matcher.is_role_def_line(line)
|
70
|
+
@assigner.assign_roles @matcher.build_role_def(line)
|
71
|
+
else
|
72
|
+
fail "Unrecognized line: #{line}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def fail(message)
|
77
|
+
@failed = true
|
78
|
+
STDERR.puts message
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_more_roles(node, roles)
|
82
|
+
@finder.find_more_roles(node, roles)
|
83
|
+
end
|
84
|
+
|
85
|
+
def find_grandchild_roles(roles, name)
|
86
|
+
@finder.find_grandchild_roles(roles, name)
|
87
|
+
end
|
88
|
+
|
89
|
+
def find_child_roles(roles, name)
|
90
|
+
@finder.find_child_roles(roles, name)
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_constraints(role)
|
94
|
+
@constraints.get_constraints(role)
|
95
|
+
end
|
96
|
+
|
97
|
+
def field_allowed?(roles, child)
|
98
|
+
@allowed_fields.allowed?(roles, child)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
module J2119
|
15
|
+
|
16
|
+
# Just a hash to remember constraints
|
17
|
+
class RoleConstraints
|
18
|
+
def initialize
|
19
|
+
@constraints = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def add(role, constraint)
|
23
|
+
@constraints[role] ||= []
|
24
|
+
@constraints[role] << constraint
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_constraints(role)
|
28
|
+
@constraints[role] || []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
module J2119
|
15
|
+
|
16
|
+
# This is about figuring out which roles apply to a node and
|
17
|
+
# potentially to its children in object and array valued fields
|
18
|
+
#
|
19
|
+
class RoleFinder
|
20
|
+
|
21
|
+
# for debugging
|
22
|
+
attr_reader :field_value_roles
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
# roles of the form: If an object with role X has field Y which
|
26
|
+
# is an object, that object has role R
|
27
|
+
@child_roles = {}
|
28
|
+
|
29
|
+
# roles of the form: If an object with role X has field Y which
|
30
|
+
# is an object/array, the object-files/array-elements have role R
|
31
|
+
@grandchild_roles = {}
|
32
|
+
|
33
|
+
# roles of the form: If an object with role X has a field Y with
|
34
|
+
# value Z, it has role R
|
35
|
+
# map[role][field_name][field_val] => child_role
|
36
|
+
@field_value_roles = {}
|
37
|
+
|
38
|
+
# roles of the form: If an object with role X has a field Y, then
|
39
|
+
# it has role R
|
40
|
+
# map[role][field_name] => child_role
|
41
|
+
@field_presence_roles = {}
|
42
|
+
|
43
|
+
# roles of the form: A Foo is a Bar
|
44
|
+
@is_a_roles = {}
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_is_a_role(role, other_role)
|
48
|
+
@is_a_roles[role] ||= []
|
49
|
+
@is_a_roles[role] << other_role
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_field_value_role(role, field_name, field_value, new_role)
|
53
|
+
@field_value_roles[role] ||= {}
|
54
|
+
@field_value_roles[role][field_name] ||= {}
|
55
|
+
field_value = Deduce.value(field_value)
|
56
|
+
|
57
|
+
@field_value_roles[role][field_name][field_value] = new_role
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_field_presence_role(role, field_name, new_role)
|
61
|
+
@field_presence_roles[role] ||= {}
|
62
|
+
@field_presence_roles[role][field_name] = new_role
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_child_role(role, field_name, child_role)
|
66
|
+
@child_roles[role] ||= {}
|
67
|
+
@child_roles[role][field_name] = child_role
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_grandchild_role(role, field_name, child_role)
|
71
|
+
@grandchild_roles[role] ||= {}
|
72
|
+
@grandchild_roles[role][field_name] = child_role
|
73
|
+
end
|
74
|
+
|
75
|
+
# Consider a node which has one or more roles. It may have more
|
76
|
+
# roles based on the presence or value of child nodes. This method
|
77
|
+
# addes any such roles to the "roles" list
|
78
|
+
#
|
79
|
+
def find_more_roles(node, roles)
|
80
|
+
|
81
|
+
# find roles depending on field values
|
82
|
+
roles.each do |role|
|
83
|
+
per_field_name = @field_value_roles[role]
|
84
|
+
if per_field_name
|
85
|
+
per_field_name.each do |field_name, value_roles|
|
86
|
+
value_roles.each do |field_value, child_role|
|
87
|
+
if field_value == node[field_name]
|
88
|
+
roles << child_role
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# find roles depending on field presence
|
96
|
+
roles.each do |role|
|
97
|
+
per_field_name = @field_presence_roles[role]
|
98
|
+
if per_field_name
|
99
|
+
per_field_name.each do |field_name, child_role|
|
100
|
+
if node.key? field_name
|
101
|
+
roles << child_role
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# is_a roles
|
108
|
+
roles.each do |role|
|
109
|
+
other_roles = @is_a_roles[role]
|
110
|
+
if other_roles
|
111
|
+
other_roles.each { |o| roles << o }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# A node has a role, and one of its fields might be object-valued
|
117
|
+
# and that value is given a role
|
118
|
+
def find_child_roles(roles, field_name)
|
119
|
+
newroles = []
|
120
|
+
roles.each do |role|
|
121
|
+
if @child_roles[role] && @child_roles[role][field_name]
|
122
|
+
newroles << @child_roles[role][field_name]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
newroles
|
126
|
+
end
|
127
|
+
|
128
|
+
# A node has a role, and one of its field is an object or an
|
129
|
+
# array whose fields or elements are given a role
|
130
|
+
#
|
131
|
+
def find_grandchild_roles(roles, field_name)
|
132
|
+
newroles = []
|
133
|
+
roles.each do |role|
|
134
|
+
if @grandchild_roles[role] && @grandchild_roles[role][field_name]
|
135
|
+
newroles << @grandchild_roles[role][field_name]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
newroles
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
data/lib/j2119.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may
|
4
|
+
# not use this file except in compliance with the License. A copy of the
|
5
|
+
# License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the LICENSE.txt file accompanying this file. This file is distributed
|
10
|
+
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
11
|
+
# express or implied. See the License for the specific language governing
|
12
|
+
# permissions and limitations under the License.
|
13
|
+
|
14
|
+
require 'json'
|
15
|
+
$:.unshift("#{File.expand_path(File.dirname(__FILE__))}/../lib")
|
16
|
+
require 'j2119/assigner'
|
17
|
+
require 'j2119/conditional'
|
18
|
+
require 'j2119/constraints'
|
19
|
+
require 'j2119/deduce'
|
20
|
+
require 'j2119/matcher'
|
21
|
+
require 'j2119/node_validator'
|
22
|
+
require 'j2119/oxford'
|
23
|
+
require 'j2119/parser'
|
24
|
+
require 'j2119/role_constraints'
|
25
|
+
require 'j2119/role_finder'
|
26
|
+
require 'j2119/allowed_fields'
|
27
|
+
require 'j2119/json_path_checker'
|
28
|
+
|
29
|
+
module J2119
|
30
|
+
|
31
|
+
class Validator
|
32
|
+
|
33
|
+
attr_reader :parsed
|
34
|
+
|
35
|
+
def initialize assertions_source
|
36
|
+
assertions = File.open(assertions_source, "r")
|
37
|
+
@parser = Parser.new assertions
|
38
|
+
end
|
39
|
+
|
40
|
+
def root
|
41
|
+
@parser.root
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate json_source
|
45
|
+
# already parsed?
|
46
|
+
if json_source.is_a?(Hash)
|
47
|
+
@parsed = json_source
|
48
|
+
else
|
49
|
+
if json_source.respond_to?(:read)
|
50
|
+
text = json_source.read
|
51
|
+
elsif File.readable? json_source
|
52
|
+
text = File.read json_source
|
53
|
+
else
|
54
|
+
text = json_source
|
55
|
+
end
|
56
|
+
begin
|
57
|
+
@parsed = JSON.parse text
|
58
|
+
rescue Exception => e
|
59
|
+
return [ "Problem reading/parsing JSON: #{e.to_s}" ]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
problems = []
|
64
|
+
validator = NodeValidator.new(@parser)
|
65
|
+
validator.validate_node(@parsed,
|
66
|
+
@parser.root,
|
67
|
+
[ @parser.root ],
|
68
|
+
problems)
|
69
|
+
problems
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_s
|
73
|
+
"J2119 validator for instances of \"#{@parser.root}\""
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: j2119
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Bray
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Validates JSON objects based on constraints in RFC2119-like language
|
28
|
+
email: timbray@amazon.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- Gemfile
|
35
|
+
- LICENSE
|
36
|
+
- NOTICE.txt
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- j2119.gemspec
|
40
|
+
- lib/j2119.rb
|
41
|
+
- lib/j2119/allowed_fields.rb
|
42
|
+
- lib/j2119/assigner.rb
|
43
|
+
- lib/j2119/conditional.rb
|
44
|
+
- lib/j2119/constraints.rb
|
45
|
+
- lib/j2119/deduce.rb
|
46
|
+
- lib/j2119/json_path_checker.rb
|
47
|
+
- lib/j2119/matcher.rb
|
48
|
+
- lib/j2119/node_validator.rb
|
49
|
+
- lib/j2119/oxford.rb
|
50
|
+
- lib/j2119/parser.rb
|
51
|
+
- lib/j2119/role_constraints.rb
|
52
|
+
- lib/j2119/role_finder.rb
|
53
|
+
homepage: http://rubygems.org/gems/j2119
|
54
|
+
licenses:
|
55
|
+
- Apache 2.0
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.0.14.1
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: JSON DSL Validator
|
77
|
+
test_files: []
|