jsi 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +6 -1
- data/CHANGELOG.md +33 -0
- data/LICENSE.md +1 -1
- data/README.md +29 -23
- data/jsi.gemspec +29 -0
- data/lib/jsi/base/mutability.rb +44 -0
- data/lib/jsi/base/node.rb +348 -0
- data/lib/jsi/base.rb +497 -339
- data/lib/jsi/jsi_coder.rb +19 -17
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +61 -26
- data/lib/jsi/metaschema_node.rb +161 -133
- data/lib/jsi/ptr.rb +80 -47
- data/lib/jsi/schema/application/child_application/contains.rb +11 -2
- data/lib/jsi/schema/application/child_application/draft04.rb +0 -1
- data/lib/jsi/schema/application/child_application/draft06.rb +0 -1
- data/lib/jsi/schema/application/child_application/draft07.rb +0 -1
- data/lib/jsi/schema/application/child_application/items.rb +3 -3
- data/lib/jsi/schema/application/child_application/properties.rb +3 -3
- data/lib/jsi/schema/application/child_application.rb +0 -27
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +1 -1
- data/lib/jsi/schema/application/inplace_application/draft04.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/draft06.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/draft07.rb +0 -1
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +3 -3
- data/lib/jsi/schema/application/inplace_application/ref.rb +2 -2
- data/lib/jsi/schema/application/inplace_application/someof.rb +26 -11
- data/lib/jsi/schema/application/inplace_application.rb +0 -32
- data/lib/jsi/schema/draft04.rb +0 -1
- data/lib/jsi/schema/draft06.rb +0 -1
- data/lib/jsi/schema/draft07.rb +0 -1
- data/lib/jsi/schema/ref.rb +46 -19
- data/lib/jsi/schema/schema_ancestor_node.rb +69 -66
- data/lib/jsi/schema/validation/array.rb +3 -3
- data/lib/jsi/schema/validation/const.rb +1 -1
- data/lib/jsi/schema/validation/contains.rb +2 -2
- data/lib/jsi/schema/validation/dependencies.rb +1 -1
- data/lib/jsi/schema/validation/draft04/minmax.rb +8 -6
- data/lib/jsi/schema/validation/draft04.rb +0 -2
- data/lib/jsi/schema/validation/draft06.rb +0 -2
- data/lib/jsi/schema/validation/draft07.rb +0 -2
- data/lib/jsi/schema/validation/enum.rb +1 -1
- data/lib/jsi/schema/validation/ifthenelse.rb +5 -5
- data/lib/jsi/schema/validation/items.rb +7 -7
- data/lib/jsi/schema/validation/not.rb +1 -1
- data/lib/jsi/schema/validation/numeric.rb +5 -5
- data/lib/jsi/schema/validation/object.rb +2 -2
- data/lib/jsi/schema/validation/pattern.rb +2 -2
- data/lib/jsi/schema/validation/properties.rb +7 -7
- data/lib/jsi/schema/validation/property_names.rb +1 -1
- data/lib/jsi/schema/validation/ref.rb +2 -2
- data/lib/jsi/schema/validation/required.rb +1 -1
- data/lib/jsi/schema/validation/someof.rb +3 -3
- data/lib/jsi/schema/validation/string.rb +2 -2
- data/lib/jsi/schema/validation/type.rb +1 -1
- data/lib/jsi/schema/validation.rb +1 -3
- data/lib/jsi/schema.rb +443 -226
- data/lib/jsi/schema_classes.rb +241 -147
- data/lib/jsi/schema_registry.rb +78 -19
- data/lib/jsi/schema_set.rb +114 -28
- data/lib/jsi/simple_wrap.rb +18 -4
- data/lib/jsi/util/private/attr_struct.rb +141 -0
- data/lib/jsi/util/private/memo_map.rb +75 -0
- data/lib/jsi/util/private.rb +185 -0
- data/lib/jsi/{typelike_modules.rb → util/typelike.rb} +79 -105
- data/lib/jsi/util.rb +157 -153
- data/lib/jsi/validation/error.rb +4 -0
- data/lib/jsi/validation/result.rb +18 -32
- data/lib/jsi/version.rb +1 -1
- data/lib/jsi.rb +65 -39
- data/lib/schemas/json-schema.org/draft-04/schema.rb +160 -3
- data/lib/schemas/json-schema.org/draft-06/schema.rb +162 -3
- data/lib/schemas/json-schema.org/draft-07/schema.rb +189 -3
- metadata +27 -11
- data/lib/jsi/metaschema.rb +0 -7
- data/lib/jsi/pathed_node.rb +0 -116
- data/lib/jsi/schema/validation/core.rb +0 -39
- data/lib/jsi/util/attr_struct.rb +0 -106
data/lib/jsi/schema_classes.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JSI
|
4
|
-
#
|
5
|
-
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
# note: defined on JSI Schema Module by JSI::SchemaClasses.module_for_schema
|
4
|
+
# A Module associated with a JSI Schema. See {Schema#jsi_schema_module}.
|
5
|
+
class SchemaModule < Module
|
6
|
+
# @private
|
7
|
+
def initialize(schema, &block)
|
8
|
+
super(&block)
|
10
9
|
|
10
|
+
@jsi_node = schema
|
11
|
+
|
12
|
+
schema.jsi_schemas.each do |schema_schema|
|
13
|
+
extend SchemaClasses.schema_property_reader_module(schema_schema, conflicting_modules: Set[SchemaModule])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# The schema for which this is the JSI Schema Module
|
18
|
+
# @return [Base + Schema]
|
19
|
+
def schema
|
20
|
+
@jsi_node
|
21
|
+
end
|
11
22
|
|
12
23
|
# a URI which refers to the schema. see {Schema#schema_uri}.
|
13
24
|
# @return (see Schema#schema_uri)
|
@@ -18,256 +29,339 @@ module JSI
|
|
18
29
|
# @return [String]
|
19
30
|
def inspect
|
20
31
|
if name_from_ancestor
|
21
|
-
|
32
|
+
if schema.schema_absolute_uri
|
33
|
+
-"#{name_from_ancestor} <#{schema.schema_absolute_uri}> (JSI Schema Module)"
|
34
|
+
else
|
35
|
+
-"#{name_from_ancestor} (JSI Schema Module)"
|
36
|
+
end
|
22
37
|
else
|
23
|
-
"(JSI Schema Module: #{schema.schema_uri || schema.jsi_ptr.uri})"
|
38
|
+
-"(JSI Schema Module: #{schema.schema_uri || schema.jsi_ptr.uri})"
|
24
39
|
end
|
25
40
|
end
|
26
41
|
|
27
|
-
|
42
|
+
def to_s
|
43
|
+
inspect
|
44
|
+
end
|
45
|
+
|
46
|
+
# invokes {JSI::Schema#new_jsi} on this module's schema, passing the given parameters.
|
28
47
|
#
|
29
48
|
# @param (see JSI::Schema#new_jsi)
|
30
|
-
# @return [JSI::Base] a JSI whose
|
31
|
-
|
32
|
-
|
49
|
+
# @return [JSI::Base subclass] a JSI whose content comes from the given instance and whose schemas are
|
50
|
+
# inplace applicators of this module's schema.
|
51
|
+
def new_jsi(instance, **kw)
|
52
|
+
schema.new_jsi(instance, **kw)
|
53
|
+
end
|
54
|
+
|
55
|
+
# See {Schema#schema_content}
|
56
|
+
def schema_content
|
57
|
+
schema.jsi_node_content
|
58
|
+
end
|
59
|
+
|
60
|
+
# See {Schema#instance_validate}
|
61
|
+
def instance_validate(instance)
|
62
|
+
schema.instance_validate(instance)
|
63
|
+
end
|
64
|
+
|
65
|
+
# See {Schema#instance_valid?}
|
66
|
+
def instance_valid?(instance)
|
67
|
+
schema.instance_valid?(instance)
|
33
68
|
end
|
34
69
|
end
|
35
70
|
|
36
|
-
#
|
37
|
-
module
|
38
|
-
#
|
71
|
+
# A module to extend the {SchemaModule} of a schema which describes other schemas (a {Schema::MetaSchema})
|
72
|
+
module SchemaModule::MetaSchemaModule
|
73
|
+
# Instantiates the given schema content as a JSI Schema.
|
39
74
|
#
|
40
|
-
# see {JSI::Schema::
|
75
|
+
# see {JSI::Schema::MetaSchema#new_schema}
|
41
76
|
#
|
42
|
-
# @param (see
|
43
|
-
# @
|
44
|
-
#
|
45
|
-
|
46
|
-
|
77
|
+
# @param (see Schema::MetaSchema#new_schema)
|
78
|
+
# @yield (see Schema::MetaSchema#new_schema)
|
79
|
+
# @return [JSI::Base subclass + JSI::Schema] a JSI which is a {JSI::Schema} whose content comes from
|
80
|
+
# the given `schema_content` and whose schemas are inplace applicators of this module's schema
|
81
|
+
def new_schema(schema_content, **kw, &block)
|
82
|
+
schema.new_schema(schema_content, **kw, &block)
|
47
83
|
end
|
48
84
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
# @return [Module
|
55
|
-
def
|
56
|
-
schema.
|
85
|
+
# (see Schema::MetaSchema#new_schema_module)
|
86
|
+
def new_schema_module(schema_content, **kw, &block)
|
87
|
+
schema.new_schema(schema_content, **kw, &block).jsi_schema_module
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Set<Module>]
|
91
|
+
def schema_implementation_modules
|
92
|
+
schema.schema_implementation_modules
|
57
93
|
end
|
58
94
|
end
|
59
95
|
|
60
96
|
# this module is a namespace for building schema classes and schema modules.
|
97
|
+
# @api private
|
61
98
|
module SchemaClasses
|
62
|
-
extend Util::Memoize
|
63
|
-
|
64
99
|
class << self
|
100
|
+
# @private
|
101
|
+
# @return [Set<Module>]
|
102
|
+
def includes_for(instance)
|
103
|
+
includes = Set[]
|
104
|
+
includes << Base::ArrayNode if instance.respond_to?(:to_ary)
|
105
|
+
includes << Base::HashNode if instance.respond_to?(:to_hash)
|
106
|
+
includes << Base::StringNode if instance.respond_to?(:to_str)
|
107
|
+
includes.freeze
|
108
|
+
end
|
109
|
+
|
65
110
|
# a JSI Schema Class which represents the given schemas.
|
66
111
|
# an instance of the class is a JSON Schema instance described by all of the given schemas.
|
67
|
-
# @private
|
112
|
+
# @api private
|
68
113
|
# @param schemas [Enumerable<JSI::Schema>] schemas which the class will represent
|
114
|
+
# @param includes [Enumerable<Module>] modules which will be included on the class
|
69
115
|
# @return [Class subclassing JSI::Base]
|
70
|
-
def class_for_schemas(schemas)
|
71
|
-
|
116
|
+
def class_for_schemas(schemas, includes: , mutable: )
|
117
|
+
@class_for_schemas_map[
|
118
|
+
schemas: SchemaSet.ensure_schema_set(schemas),
|
119
|
+
includes: Util.ensure_module_set(includes),
|
120
|
+
mutable: mutable,
|
121
|
+
]
|
122
|
+
end
|
72
123
|
|
73
|
-
|
74
|
-
Class.new(Base)
|
124
|
+
private def class_for_schemas_compute(schemas: , includes: , mutable: )
|
125
|
+
Class.new(Base) do
|
75
126
|
define_singleton_method(:jsi_class_schemas) { schemas }
|
76
127
|
define_method(:jsi_schemas) { schemas }
|
128
|
+
|
129
|
+
define_singleton_method(:jsi_class_includes) { includes }
|
130
|
+
|
131
|
+
mutability_module = mutable ? Base::Mutable : Base::Immutable
|
132
|
+
conflicting_modules = Set[JSI::Base, mutability_module] + includes + schemas.map(&:jsi_schema_module)
|
133
|
+
|
134
|
+
include(mutability_module)
|
135
|
+
|
136
|
+
reader_modules = schemas.map do |schema|
|
137
|
+
JSI::SchemaClasses.schema_property_reader_module(schema, conflicting_modules: conflicting_modules)
|
138
|
+
end
|
139
|
+
reader_modules.each { |m| include m }
|
140
|
+
readers = reader_modules.map(&:jsi_property_readers).inject(Set[], &:merge).freeze
|
141
|
+
define_method(:jsi_property_readers) { readers }
|
142
|
+
define_singleton_method(:jsi_property_readers) { readers }
|
143
|
+
|
144
|
+
if mutable
|
145
|
+
writer_modules = schemas.map do |schema|
|
146
|
+
JSI::SchemaClasses.schema_property_writer_module(schema, conflicting_modules: conflicting_modules)
|
147
|
+
end
|
148
|
+
writer_modules.each { |m| include(m) }
|
149
|
+
end
|
150
|
+
|
151
|
+
includes.each { |m| include(m) }
|
77
152
|
schemas.each { |schema| include(schema.jsi_schema_module) }
|
78
153
|
jsi_class = self
|
79
154
|
define_method(:jsi_class) { jsi_class }
|
80
155
|
|
81
156
|
self
|
82
157
|
end
|
83
|
-
end
|
84
158
|
end
|
85
159
|
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# @param modules [Set<Module>]
|
160
|
+
# a subclass of MetaSchemaNode::BootstrapSchema with the given modules included
|
161
|
+
# @api private
|
162
|
+
# @param modules [Set<Module>] schema implementation modules
|
89
163
|
# @return [Class]
|
90
164
|
def bootstrap_schema_class(modules)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
165
|
+
@bootstrap_schema_class_map[
|
166
|
+
modules: Util.ensure_module_set(modules),
|
167
|
+
]
|
168
|
+
end
|
169
|
+
|
170
|
+
private def bootstrap_schema_class_compute(modules: )
|
171
|
+
Class.new(MetaSchemaNode::BootstrapSchema) do
|
172
|
+
define_singleton_method(:schema_implementation_modules) { modules }
|
173
|
+
define_method(:schema_implementation_modules) { modules }
|
96
174
|
modules.each { |mod| include(mod) }
|
97
175
|
|
98
176
|
self
|
99
177
|
end
|
100
|
-
end
|
101
178
|
end
|
102
179
|
|
103
180
|
# see {Schema#jsi_schema_module}
|
104
181
|
# @api private
|
105
|
-
# @return [
|
182
|
+
# @return [SchemaModule]
|
106
183
|
def module_for_schema(schema)
|
107
184
|
Schema.ensure_schema(schema)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
define_singleton_method(:schema) { schema }
|
185
|
+
raise(Bug, "non-Base schema cannot have schema module: #{schema}") unless schema.is_a?(Base)
|
186
|
+
@schema_module_map[schema]
|
187
|
+
end
|
112
188
|
|
113
|
-
|
189
|
+
# @private
|
190
|
+
# @deprecated after v0.7
|
191
|
+
def accessor_module_for_schema(schema, conflicting_modules: , setters: true)
|
192
|
+
Module.new do
|
193
|
+
include SchemaClasses.schema_property_reader_module(schema, conflicting_modules: conflicting_modules)
|
194
|
+
include SchemaClasses.schema_property_writer_module(schema, conflicting_modules: conflicting_modules) if setters
|
195
|
+
end
|
196
|
+
end
|
114
197
|
|
115
|
-
|
116
|
-
|
117
|
-
|
198
|
+
# a module of readers for described property names of the given schema.
|
199
|
+
#
|
200
|
+
# @private
|
201
|
+
# @param schema [JSI::Schema] a schema for which to define readers for any described property names
|
202
|
+
# @param conflicting_modules [Enumerable<Module>] an array of modules (or classes) which
|
203
|
+
# may be used alongside the accessor module. methods defined by any conflicting_module
|
204
|
+
# will not be defined as accessors.
|
205
|
+
# @return [Module]
|
206
|
+
def schema_property_reader_module(schema, conflicting_modules: )
|
207
|
+
Schema.ensure_schema(schema)
|
208
|
+
@schema_property_reader_module_map[schema: schema, conflicting_modules: conflicting_modules]
|
209
|
+
end
|
118
210
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
)
|
123
|
-
|
211
|
+
private def schema_property_reader_module_compute(schema: , conflicting_modules: )
|
212
|
+
Module.new do
|
213
|
+
readers = schema.described_object_property_names.select do |name|
|
214
|
+
Util.ok_ruby_method_name?(name) &&
|
215
|
+
!conflicting_modules.any? { |m| m.method_defined?(name) || m.private_method_defined?(name) }
|
216
|
+
end.to_set.freeze
|
124
217
|
|
125
|
-
|
218
|
+
define_singleton_method(:inspect) { "(JSI Schema Property Reader Module: #{readers.join(', ')})" }
|
126
219
|
|
127
|
-
|
128
|
-
extend DescribesSchemaModule
|
129
|
-
end
|
220
|
+
define_singleton_method(:jsi_property_readers) { readers }
|
130
221
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
extend JSI::SchemaClasses.accessor_module_for_schema(schema_schema,
|
135
|
-
conflicting_modules: Set[Module, SchemaModule, SchemaModulePossibly],
|
136
|
-
setters: false,
|
137
|
-
)
|
222
|
+
readers.each do |property_name|
|
223
|
+
define_method(property_name) do |**kw, &block|
|
224
|
+
self[property_name, **kw, &block]
|
138
225
|
end
|
139
226
|
end
|
140
227
|
end
|
141
|
-
end
|
142
228
|
end
|
143
229
|
|
144
|
-
# a module of
|
145
|
-
#
|
146
|
-
|
147
|
-
# @param conflicting_modules [Enumerable<Module>] an array of modules (or classes) which
|
148
|
-
# may be used alongside the accessor module. methods defined by any conflicting_module
|
149
|
-
# will not be defined as accessors.
|
150
|
-
# @param setters [Boolean] whether to define setter methods
|
151
|
-
# @return [Module]
|
152
|
-
def accessor_module_for_schema(schema, conflicting_modules: , setters: true)
|
230
|
+
# a module of writers for described property names of the given schema.
|
231
|
+
# @private
|
232
|
+
def schema_property_writer_module(schema, conflicting_modules: )
|
153
233
|
Schema.ensure_schema(schema)
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
self[property_name, *a]
|
171
|
-
end
|
172
|
-
if setters
|
234
|
+
@schema_property_writer_module_map[schema: schema, conflicting_modules: conflicting_modules]
|
235
|
+
end
|
236
|
+
|
237
|
+
private def schema_property_writer_module_compute(schema: , conflicting_modules: )
|
238
|
+
Module.new do
|
239
|
+
define_singleton_method(:inspect) { '(JSI Schema Property Writer Module)' }
|
240
|
+
|
241
|
+
writers = schema.described_object_property_names.select do |name|
|
242
|
+
writer = "#{name}="
|
243
|
+
Util.ok_ruby_method_name?(name) &&
|
244
|
+
!conflicting_modules.any? { |m| m.method_defined?(writer) || m.private_method_defined?(writer) }
|
245
|
+
end.to_set.freeze
|
246
|
+
|
247
|
+
define_singleton_method(:jsi_property_writers) { writers }
|
248
|
+
|
249
|
+
writers.each do |property_name|
|
173
250
|
define_method("#{property_name}=") do |value|
|
174
251
|
self[property_name] = value
|
175
252
|
end
|
176
|
-
end
|
177
|
-
end
|
178
253
|
end
|
179
254
|
end
|
180
|
-
end
|
181
255
|
end
|
182
256
|
end
|
257
|
+
|
258
|
+
@class_for_schemas_map = Hash.new { |h, k| h[k] = class_for_schemas_compute(**k) }
|
259
|
+
@bootstrap_schema_class_map = Hash.new { |h, k| h[k] = bootstrap_schema_class_compute(**k) }
|
260
|
+
@schema_module_map = Hash.new { |h, schema| h[schema] = SchemaModule.new(schema) }
|
261
|
+
@schema_property_reader_module_map = Hash.new { |h, k| h[k] = schema_property_reader_module_compute(**k) }
|
262
|
+
@schema_property_writer_module_map = Hash.new { |h, k| h[k] = schema_property_writer_module_compute(**k) }
|
183
263
|
end
|
184
264
|
|
185
|
-
#
|
186
|
-
|
187
|
-
|
188
|
-
attr_reader :possibly_schema_node
|
265
|
+
# connecting {SchemaModule}s via {SchemaModule::Connection}s
|
266
|
+
module SchemaModule::Connects
|
267
|
+
attr_reader :jsi_node
|
189
268
|
|
190
269
|
# a name relative to a named schema module of an ancestor schema.
|
191
|
-
# for example, if `Foos = JSI::
|
270
|
+
# for example, if `Foos = JSI::JSONSchemaDraft07.new_schema_module({'items' => {}})`
|
192
271
|
# then the module `Foos.items` will have a name_from_ancestor of `"Foos.items"`
|
272
|
+
# @api private
|
193
273
|
# @return [String, nil]
|
194
274
|
def name_from_ancestor
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
return nil unless named_parent_schema
|
275
|
+
named_ancestor_schema, tokens = named_ancestor_schema_tokens
|
276
|
+
return nil unless named_ancestor_schema
|
199
277
|
|
200
|
-
|
201
|
-
|
202
|
-
parent = named_parent_schema
|
278
|
+
name = named_ancestor_schema.jsi_schema_module.name
|
279
|
+
ancestor = named_ancestor_schema
|
203
280
|
tokens.each do |token|
|
204
|
-
if
|
281
|
+
if ancestor.jsi_property_readers.include?(token)
|
205
282
|
name += ".#{token}"
|
206
283
|
elsif [String, Numeric, TrueClass, FalseClass, NilClass].any? { |m| token.is_a?(m) }
|
207
284
|
name += "[#{token.inspect}]"
|
208
285
|
else
|
209
286
|
return nil
|
210
287
|
end
|
211
|
-
|
288
|
+
ancestor = ancestor[token]
|
212
289
|
end
|
213
|
-
name
|
290
|
+
name.freeze
|
214
291
|
end
|
215
292
|
|
216
|
-
#
|
217
|
-
# if the result is a JSI::Schema, return the JSI Schema module of that schema; if it is a
|
218
|
-
# return a
|
293
|
+
# Subscripting a JSI schema module or a {SchemaModule::Connection} will subscript its node, and
|
294
|
+
# if the result is a JSI::Schema, return the JSI Schema module of that schema; if it is a JSI::Base,
|
295
|
+
# return a SchemaModule::Connection; or if it is another value (a basic type), return that value.
|
219
296
|
#
|
220
297
|
# @param token [Object]
|
221
|
-
# @
|
222
|
-
|
223
|
-
|
298
|
+
# @yield If the token identifies a schema and a block is given,
|
299
|
+
# it is evaluated in the context of the schema's JSI schema module
|
300
|
+
# using [Module#module_exec](https://ruby-doc.org/core/Module.html#method-i-module_exec).
|
301
|
+
# @return [SchemaModule, SchemaModule::Connection, Object]
|
302
|
+
def [](token, **kw, &block)
|
303
|
+
raise(ArgumentError) unless kw.empty? # TODO remove eventually (keyword argument compatibility)
|
304
|
+
sub = @jsi_node[token]
|
224
305
|
if sub.is_a?(JSI::Schema)
|
306
|
+
sub.jsi_schema_module_exec(&block) if block
|
225
307
|
sub.jsi_schema_module
|
226
|
-
elsif
|
227
|
-
|
308
|
+
elsif block
|
309
|
+
raise(ArgumentError, "block given but token #{token.inspect} does not identify a schema")
|
310
|
+
elsif sub.is_a?(JSI::Base)
|
311
|
+
SchemaModule::Connection.new(sub)
|
228
312
|
else
|
229
313
|
sub
|
230
314
|
end
|
231
315
|
end
|
316
|
+
|
317
|
+
private
|
318
|
+
|
319
|
+
# @return [Array<JSI::Schema, Array>, nil]
|
320
|
+
def named_ancestor_schema_tokens
|
321
|
+
schema_ancestors = @jsi_node.jsi_ancestor_nodes
|
322
|
+
named_ancestor_schema = schema_ancestors.detect { |jsi| jsi.is_a?(JSI::Schema) && jsi.jsi_schema_module.name }
|
323
|
+
return nil unless named_ancestor_schema
|
324
|
+
tokens = @jsi_node.jsi_ptr.relative_to(named_ancestor_schema.jsi_ptr).tokens
|
325
|
+
[named_ancestor_schema, tokens]
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
class SchemaModule
|
330
|
+
include Connects
|
232
331
|
end
|
233
332
|
|
234
|
-
#
|
333
|
+
# A JSI Schema Module is a module which represents a schema. A SchemaModule::Connection represents
|
235
334
|
# a node in a schema's document which is not a schema, such as the 'properties'
|
236
335
|
# object (which contains schemas but is not a schema).
|
237
336
|
#
|
238
337
|
# instances of this class act as a stand-in to allow users to subscript or call property accessors on
|
239
338
|
# schema modules to refer to their subschemas' schema modules.
|
240
339
|
#
|
241
|
-
#
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
# value is a basic type - that value itself is returned.
|
247
|
-
class NotASchemaModule
|
248
|
-
# @param node [JSI::PathedNode]
|
340
|
+
# A SchemaModule::Connection has readers for property names described by the node's schemas.
|
341
|
+
class SchemaModule::Connection
|
342
|
+
include SchemaModule::Connects
|
343
|
+
|
344
|
+
# @param node [JSI::Base]
|
249
345
|
def initialize(node)
|
250
|
-
unless node.is_a?(JSI::
|
251
|
-
|
252
|
-
|
253
|
-
if node.is_a?(JSI::Schema)
|
254
|
-
raise(TypeError, "cannot instantiate NotASchemaModule for a JSI::Schema node: #{node.pretty_inspect.chomp}")
|
255
|
-
end
|
256
|
-
@possibly_schema_node = node
|
346
|
+
raise(Bug, "node must be JSI::Base: #{node.pretty_inspect.chomp}") unless node.is_a?(JSI::Base)
|
347
|
+
raise(Bug, "node must not be JSI::Schema: #{node.pretty_inspect.chomp}") if node.is_a?(JSI::Schema)
|
348
|
+
@jsi_node = node
|
257
349
|
node.jsi_schemas.each do |schema|
|
258
|
-
extend(JSI::SchemaClasses.
|
350
|
+
extend(JSI::SchemaClasses.schema_property_reader_module(schema, conflicting_modules: [SchemaModule::Connection]))
|
259
351
|
end
|
260
352
|
end
|
261
353
|
|
262
|
-
include SchemaModulePossibly
|
263
|
-
|
264
354
|
# @return [String]
|
265
355
|
def inspect
|
266
356
|
if name_from_ancestor
|
267
|
-
"#{name_from_ancestor} (
|
357
|
+
-"#{name_from_ancestor} (#{self.class})"
|
268
358
|
else
|
269
|
-
"(
|
359
|
+
-"(#{self.class}: #{@jsi_node.jsi_ptr.uri})"
|
270
360
|
end
|
271
361
|
end
|
362
|
+
|
363
|
+
def to_s
|
364
|
+
inspect
|
365
|
+
end
|
272
366
|
end
|
273
367
|
end
|