jsi 0.7.0 → 0.8.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 +4 -4
- data/.yardopts +6 -1
- data/CHANGELOG.md +15 -0
- data/README.md +19 -18
- data/jsi.gemspec +2 -3
- data/lib/jsi/base/mutability.rb +44 -0
- data/lib/jsi/base/node.rb +199 -34
- data/lib/jsi/base.rb +412 -228
- data/lib/jsi/jsi_coder.rb +18 -16
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +57 -23
- data/lib/jsi/metaschema_node.rb +138 -107
- data/lib/jsi/ptr.rb +59 -37
- 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.rb +0 -25
- 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/ref.rb +1 -1
- data/lib/jsi/schema/application/inplace_application/someof.rb +1 -1
- data/lib/jsi/schema/application/inplace_application.rb +0 -27
- 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 +44 -18
- data/lib/jsi/schema/schema_ancestor_node.rb +65 -56
- data/lib/jsi/schema/validation/contains.rb +1 -1
- data/lib/jsi/schema/validation/draft04/minmax.rb +2 -0
- 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/items.rb +3 -3
- data/lib/jsi/schema/validation/pattern.rb +1 -1
- data/lib/jsi/schema/validation/properties.rb +4 -4
- data/lib/jsi/schema/validation/ref.rb +1 -1
- data/lib/jsi/schema/validation.rb +0 -2
- data/lib/jsi/schema.rb +405 -194
- data/lib/jsi/schema_classes.rb +196 -127
- data/lib/jsi/schema_registry.rb +66 -17
- data/lib/jsi/schema_set.rb +76 -30
- data/lib/jsi/simple_wrap.rb +2 -7
- data/lib/jsi/util/private/attr_struct.rb +28 -14
- data/lib/jsi/util/private/memo_map.rb +75 -0
- data/lib/jsi/util/private.rb +73 -92
- data/lib/jsi/util/typelike.rb +28 -28
- data/lib/jsi/util.rb +120 -36
- 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 +67 -25
- data/lib/schemas/json-schema.org/draft-04/schema.rb +159 -4
- data/lib/schemas/json-schema.org/draft-06/schema.rb +161 -4
- data/lib/schemas/json-schema.org/draft-07/schema.rb +188 -4
- metadata +19 -5
- data/lib/jsi/metaschema.rb +0 -6
- data/lib/jsi/schema/validation/core.rb +0 -39
data/lib/jsi/jsi_coder.rb
CHANGED
@@ -29,12 +29,16 @@ module JSI
|
|
29
29
|
# will instantiate column data using the JSI schemas represented.
|
30
30
|
# @param array [Boolean] whether the dumped data represent one instance of the schema,
|
31
31
|
# or an array of them. note that it may be preferable to simply use an array schema.
|
32
|
-
|
32
|
+
# @param jsi_opt [Hash] keyword arguments to pass to {Schema#new_jsi} when loading
|
33
|
+
# @param as_json_opt [Hash] keyword arguments to pass to `#as_json` when dumping
|
34
|
+
def initialize(schema, array: false, jsi_opt: Util::EMPTY_HASH, as_json_opt: Util::EMPTY_HASH)
|
33
35
|
unless schema.respond_to?(:new_jsi)
|
34
36
|
raise(ArgumentError, "schema param does not respond to #new_jsi: #{schema.inspect}")
|
35
37
|
end
|
36
38
|
@schema = schema
|
37
39
|
@array = array
|
40
|
+
@jsi_opt = jsi_opt
|
41
|
+
@as_json_opt = as_json_opt
|
38
42
|
end
|
39
43
|
|
40
44
|
# loads the database column to JSI instances of our schema
|
@@ -44,7 +48,8 @@ module JSI
|
|
44
48
|
# instance(s), or nil if data is nil
|
45
49
|
def load(data)
|
46
50
|
return nil if data.nil?
|
47
|
-
|
51
|
+
|
52
|
+
if @array
|
48
53
|
unless data.respond_to?(:to_ary)
|
49
54
|
raise TypeError, "expected array-like column data; got: #{data.class}: #{data.inspect}"
|
50
55
|
end
|
@@ -52,7 +57,6 @@ module JSI
|
|
52
57
|
else
|
53
58
|
load_object(data)
|
54
59
|
end
|
55
|
-
object
|
56
60
|
end
|
57
61
|
|
58
62
|
# dumps the object for the database
|
@@ -61,32 +65,30 @@ module JSI
|
|
61
65
|
# @return [Object, Array, nil] the schema instance(s) of the JSI(s), or nil if object is nil
|
62
66
|
def dump(object)
|
63
67
|
return nil if object.nil?
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
object.to_ary.map do |el|
|
70
|
-
dump_object(el)
|
71
|
-
end
|
72
|
-
else
|
73
|
-
dump_object(object)
|
68
|
+
|
69
|
+
if @array
|
70
|
+
unless object.respond_to?(:to_ary)
|
71
|
+
raise(TypeError, "expected array-like attribute; got: #{object.class}: #{object.inspect}")
|
74
72
|
end
|
73
|
+
object.to_ary.map do |el|
|
74
|
+
dump_object(el)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
dump_object(object)
|
75
78
|
end
|
76
|
-
jsonifiable
|
77
79
|
end
|
78
80
|
|
79
81
|
private
|
80
82
|
# @param data [Object]
|
81
83
|
# @return [JSI::Base]
|
82
84
|
def load_object(data)
|
83
|
-
@schema.new_jsi(data)
|
85
|
+
@schema.new_jsi(data, **@jsi_opt)
|
84
86
|
end
|
85
87
|
|
86
88
|
# @param object [JSI::Base, Object]
|
87
89
|
# @return [Object]
|
88
90
|
def dump_object(object)
|
89
|
-
JSI::Util.as_json(object)
|
91
|
+
JSI::Util.as_json(object, **@as_json_opt)
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
@@ -1,33 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JSI
|
4
|
-
# internal class to bootstrap a
|
4
|
+
# internal class to bootstrap a meta-schema. represents a schema without the complexity of JSI::Base. the
|
5
5
|
# schema is represented but schemas describing the schema are not.
|
6
6
|
#
|
7
7
|
# this class is to only be instantiated on nodes in the document that are known to be schemas.
|
8
8
|
# Schema#subschema and Schema#resource_root_subschema are the intended mechanisms to instantiate subschemas
|
9
9
|
# and resolve references. #[] and #jsi_root_node are not implemented.
|
10
10
|
#
|
11
|
-
# schema implementation modules are
|
11
|
+
# schema implementation modules are included on generated subclasses of BootstrapSchema by
|
12
12
|
# {SchemaClasses.bootstrap_schema_class}. that subclass is instantiated with a document and
|
13
13
|
# pointer, representing a schema.
|
14
14
|
#
|
15
|
+
# BootstrapSchema does not support mutation; its document must be immutable.
|
16
|
+
#
|
15
17
|
# @api private
|
16
|
-
class
|
17
|
-
include Util::Memoize
|
18
|
+
class MetaSchemaNode::BootstrapSchema
|
18
19
|
include Util::FingerprintHash
|
19
20
|
include Schema::SchemaAncestorNode
|
21
|
+
include Schema
|
20
22
|
|
21
23
|
class << self
|
22
24
|
def inspect
|
23
|
-
if self ==
|
24
|
-
name
|
25
|
+
if self == MetaSchemaNode::BootstrapSchema
|
26
|
+
name.freeze
|
25
27
|
else
|
26
|
-
"#{name ||
|
28
|
+
-"#{name || MetaSchemaNode::BootstrapSchema.name} (#{schema_implementation_modules.map(&:inspect).join(', ')})"
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
32
|
+
def to_s
|
33
|
+
inspect
|
34
|
+
end
|
31
35
|
end
|
32
36
|
|
33
37
|
# @param jsi_ptr [JSI::Ptr] pointer to the schema in the document
|
@@ -39,11 +43,15 @@ module JSI
|
|
39
43
|
)
|
40
44
|
raise(Bug, "no #schema_implementation_modules") unless respond_to?(:schema_implementation_modules)
|
41
45
|
|
42
|
-
jsi_initialize_memos
|
43
|
-
|
44
46
|
self.jsi_ptr = jsi_ptr
|
45
47
|
self.jsi_document = jsi_document
|
46
48
|
self.jsi_schema_base_uri = jsi_schema_base_uri
|
49
|
+
self.jsi_schema_resource_ancestors = Util::EMPTY_ARY
|
50
|
+
|
51
|
+
@jsi_node_content = jsi_ptr.evaluate(jsi_document)
|
52
|
+
#chkbug raise(Bug, 'BootstrapSchema instance must be frozen') unless jsi_node_content.frozen?
|
53
|
+
|
54
|
+
super()
|
47
55
|
end
|
48
56
|
|
49
57
|
# document containing the schema content
|
@@ -52,27 +60,47 @@ module JSI
|
|
52
60
|
# JSI::Ptr pointing to this schema within the document
|
53
61
|
attr_reader :jsi_ptr
|
54
62
|
|
55
|
-
|
56
|
-
|
63
|
+
attr_reader(:jsi_node_content)
|
64
|
+
|
65
|
+
# overrides {Schema#subschema}
|
66
|
+
def subschema(subptr)
|
67
|
+
self.class.new(
|
68
|
+
jsi_document,
|
69
|
+
jsi_ptr: jsi_ptr + subptr,
|
70
|
+
jsi_schema_base_uri: jsi_resource_ancestor_uri,
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
# overrides {Schema#resource_root_subschema}
|
75
|
+
def resource_root_subschema(ptr)
|
76
|
+
# BootstrapSchema does not track jsi_schema_resource_ancestors used by Schema#schema_resource_root;
|
77
|
+
# resource_root_subschema is always relative to the document root.
|
78
|
+
# BootstrapSchema also does not implement jsi_root_node or #[]. we instantiate the ptr directly
|
79
|
+
# rather than as a subschema from the root.
|
80
|
+
self.class.new(
|
81
|
+
jsi_document,
|
82
|
+
jsi_ptr: Ptr.ary_ptr(ptr),
|
83
|
+
jsi_schema_base_uri: nil,
|
84
|
+
)
|
57
85
|
end
|
58
86
|
|
59
87
|
# @return [String]
|
60
88
|
def inspect
|
61
|
-
"\#<#{jsi_object_group_text.join(' ')} #{schema_content.inspect}>"
|
89
|
+
-"\#<#{jsi_object_group_text.join(' ')} #{schema_content.inspect}>"
|
62
90
|
end
|
63
91
|
|
64
|
-
|
92
|
+
def to_s
|
93
|
+
inspect
|
94
|
+
end
|
65
95
|
|
66
96
|
# pretty-prints a representation of self to the given printer
|
67
97
|
# @return [void]
|
68
98
|
def pretty_print(q)
|
69
99
|
q.text '#<'
|
70
100
|
q.text jsi_object_group_text.join(' ')
|
71
|
-
q.
|
72
|
-
q.nest(2) {
|
101
|
+
q.group(2) {
|
73
102
|
q.breakable ' '
|
74
103
|
q.pp schema_content
|
75
|
-
}
|
76
104
|
}
|
77
105
|
q.breakable ''
|
78
106
|
q.text '>'
|
@@ -82,20 +110,26 @@ module JSI
|
|
82
110
|
# @return [Array<String>]
|
83
111
|
def jsi_object_group_text
|
84
112
|
[
|
85
|
-
self.class.name ||
|
86
|
-
"(#{schema_implementation_modules.map(&:inspect).join(', ')})",
|
113
|
+
self.class.name || MetaSchemaNode::BootstrapSchema.name,
|
114
|
+
-"(#{schema_implementation_modules.map(&:inspect).join(', ')})",
|
87
115
|
jsi_ptr.uri,
|
88
|
-
]
|
116
|
+
].freeze
|
89
117
|
end
|
90
118
|
|
91
|
-
#
|
119
|
+
# see {Util::Private::FingerprintHash}
|
120
|
+
# @api private
|
92
121
|
def jsi_fingerprint
|
93
122
|
{
|
94
123
|
class: self.class,
|
95
124
|
jsi_ptr: @jsi_ptr,
|
96
125
|
jsi_document: @jsi_document,
|
97
|
-
|
98
|
-
|
126
|
+
}.freeze
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def jsi_memomap_class
|
132
|
+
Util::MemoMap::Immutable
|
99
133
|
end
|
100
134
|
end
|
101
135
|
end
|
data/lib/jsi/metaschema_node.rb
CHANGED
@@ -1,36 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JSI
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# A MetaSchemaNode is a JSI instance representing a node in a document that contains a meta-schema.
|
5
|
+
# The root of the meta-schema is pointed to by metaschema_root_ptr.
|
6
6
|
# the schema describing the root of the document is pointed to by root_schema_ptr.
|
7
7
|
#
|
8
8
|
# like JSI::Base's normal subclasses, this class represents an instance of a schema set, an instance
|
9
9
|
# which may itself be a schema. unlike JSI::Base, the document containing the instance and its schemas
|
10
|
-
# is the same, and a schema (the
|
10
|
+
# is the same, and a schema (the meta-schema) may be an instance of itself.
|
11
11
|
#
|
12
12
|
# unlike JSI::Base's normal subclasses, the schemas describing the instance are not part of the class.
|
13
|
-
#
|
13
|
+
# Since the meta-schema describes itself, attempting to construct a class from the JSI Schema Module of a
|
14
14
|
# schema which is itself an instance of that class results in a causality loop.
|
15
|
-
# instead, a
|
15
|
+
# instead, a MetaSchemaNode calculates its {#jsi_schemas} and extends itself with their JSI Schema
|
16
16
|
# modules during initialization.
|
17
|
-
#
|
17
|
+
# The MetaSchemaNode of the meta-schema is extended with its own JSI Schema Module.
|
18
18
|
#
|
19
|
-
# if the
|
19
|
+
# if the MetaSchemaNode's schemas include its self, it is extended with {JSI::Schema::MetaSchema}.
|
20
20
|
#
|
21
|
-
# a
|
22
|
-
# the
|
23
|
-
class
|
21
|
+
# a MetaSchemaNode is extended with JSI::Schema when it represents a schema - this is the case when
|
22
|
+
# the meta-schema is one of its schemas.
|
23
|
+
class MetaSchemaNode < Base
|
24
24
|
autoload :BootstrapSchema, 'jsi/metaschema_node/bootstrap_schema'
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
include(Base::Immutable)
|
27
|
+
|
28
|
+
# @param jsi_document the document containing the meta-schema.
|
29
|
+
# this must be frozen recursively; MetaSchemaNode does support mutation.
|
30
|
+
# @param jsi_ptr [JSI::Ptr] ptr to this MetaSchemaNode in jsi_document
|
28
31
|
# @param schema_implementation_modules [Enumerable<Module>] modules which implement the functionality
|
29
|
-
# of the schema.
|
30
|
-
#
|
31
|
-
# the
|
32
|
+
# of the schema. These are included on the {Schema#jsi_schema_module} of the meta-schema.
|
33
|
+
# They extend any schema described by the meta-schema, including those in the document containing
|
34
|
+
# the meta-schema, and the meta-schema itself.
|
32
35
|
# see {Schema#describes_schema!} param `schema_implementation_modules`.
|
33
|
-
# @param metaschema_root_ptr [JSI::Ptr] ptr to the root of the
|
36
|
+
# @param metaschema_root_ptr [JSI::Ptr] ptr to the root of the meta-schema in the jsi_document
|
34
37
|
# @param root_schema_ptr [JSI::Ptr] ptr to the schema describing the root of the jsi_document
|
35
38
|
def initialize(
|
36
39
|
jsi_document,
|
@@ -39,31 +42,30 @@ module JSI
|
|
39
42
|
metaschema_root_ptr: Ptr[],
|
40
43
|
root_schema_ptr: Ptr[],
|
41
44
|
jsi_schema_base_uri: nil,
|
45
|
+
jsi_schema_registry: nil,
|
46
|
+
jsi_content_to_immutable: DEFAULT_CONTENT_TO_IMMUTABLE,
|
42
47
|
jsi_root_node: nil
|
43
48
|
)
|
44
|
-
|
49
|
+
super(jsi_document,
|
50
|
+
jsi_ptr: jsi_ptr,
|
51
|
+
jsi_indicated_schemas: SchemaSet[],
|
52
|
+
jsi_schema_base_uri: jsi_schema_base_uri,
|
53
|
+
jsi_schema_registry: jsi_schema_registry,
|
54
|
+
jsi_content_to_immutable: jsi_content_to_immutable,
|
55
|
+
jsi_root_node: jsi_root_node,
|
56
|
+
)
|
45
57
|
|
46
|
-
|
47
|
-
self.jsi_ptr = jsi_ptr
|
48
|
-
@schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules)
|
58
|
+
@schema_implementation_modules = schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules)
|
49
59
|
@metaschema_root_ptr = metaschema_root_ptr
|
50
60
|
@root_schema_ptr = root_schema_ptr
|
51
|
-
raise(Bug, 'jsi_root_node') if jsi_ptr.root? ^ !jsi_root_node
|
52
|
-
@jsi_root_node = jsi_ptr.root? ? self : jsi_root_node
|
53
61
|
|
54
62
|
if jsi_ptr.root? && jsi_schema_base_uri
|
55
|
-
raise(NotImplementedError, "unsupported jsi_schema_base_uri on
|
63
|
+
raise(NotImplementedError, "unsupported jsi_schema_base_uri on meta-schema document root")
|
56
64
|
end
|
57
|
-
self.jsi_schema_base_uri = jsi_schema_base_uri
|
58
65
|
|
59
|
-
|
66
|
+
#chkbug raise(Bug, 'MetaSchemaNode instance must be frozen') unless jsi_node_content.frozen?
|
60
67
|
|
61
|
-
|
62
|
-
extend HashNode
|
63
|
-
end
|
64
|
-
if jsi_node_content.respond_to?(:to_ary)
|
65
|
-
extend ArrayNode
|
66
|
-
end
|
68
|
+
extends = Set[]
|
67
69
|
|
68
70
|
instance_for_schemas = jsi_document
|
69
71
|
bootstrap_schema_class = JSI::SchemaClasses.bootstrap_schema_class(schema_implementation_modules)
|
@@ -72,68 +74,67 @@ module JSI
|
|
72
74
|
jsi_ptr: root_schema_ptr,
|
73
75
|
jsi_schema_base_uri: nil, # supplying jsi_schema_base_uri on root bootstrap schema is not supported
|
74
76
|
)
|
75
|
-
|
77
|
+
our_bootstrap_indicated_schemas = jsi_ptr.tokens.inject(SchemaSet[root_bootstrap_schema]) do |bootstrap_indicated_schemas, tok|
|
78
|
+
bootstrap_schemas = bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
|
76
79
|
child_indicated_schemas = bootstrap_schemas.child_applicator_schemas(tok, instance_for_schemas)
|
77
|
-
child_schemas = child_indicated_schemas.inplace_applicator_schemas(instance_for_schemas[tok])
|
78
80
|
instance_for_schemas = instance_for_schemas[tok]
|
79
|
-
|
81
|
+
child_indicated_schemas
|
80
82
|
end
|
83
|
+
@indicated_schemas_map = jsi_memomap { bootstrap_schemas_to_msn(our_bootstrap_indicated_schemas) }
|
81
84
|
|
85
|
+
our_bootstrap_schemas = our_bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
|
86
|
+
|
87
|
+
describes_self = false
|
82
88
|
our_bootstrap_schemas.each do |bootstrap_schema|
|
83
89
|
if bootstrap_schema.jsi_ptr == metaschema_root_ptr
|
84
|
-
# this is described by the
|
90
|
+
# this is described by the meta-schema, i.e. this is a schema
|
91
|
+
extend Schema
|
85
92
|
schema_implementation_modules.each do |schema_implementation_module|
|
86
93
|
extend schema_implementation_module
|
87
94
|
end
|
95
|
+
extends += schema_implementation_modules
|
88
96
|
end
|
89
97
|
if bootstrap_schema.jsi_ptr == jsi_ptr
|
90
|
-
# this is the
|
91
|
-
|
98
|
+
# this is the meta-schema (it is described by itself)
|
99
|
+
describes_self = true
|
92
100
|
end
|
93
101
|
end
|
94
102
|
|
95
|
-
@jsi_schemas =
|
96
|
-
if bootstrap_schema.jsi_ptr == jsi_ptr
|
97
|
-
self
|
98
|
-
elsif bootstrap_schema.jsi_ptr.root?
|
99
|
-
@jsi_root_node
|
100
|
-
else
|
101
|
-
new_node(
|
102
|
-
jsi_ptr: bootstrap_schema.jsi_ptr,
|
103
|
-
jsi_schema_base_uri: bootstrap_schema.jsi_schema_base_uri,
|
104
|
-
jsi_root_node: @jsi_root_node,
|
105
|
-
)
|
106
|
-
end
|
107
|
-
end
|
103
|
+
@jsi_schemas = bootstrap_schemas_to_msn(our_bootstrap_schemas)
|
108
104
|
|
109
105
|
# note: jsi_schemas must already be set for jsi_schema_module to be used/extended
|
110
|
-
if
|
106
|
+
if describes_self
|
111
107
|
describes_schema!(schema_implementation_modules)
|
112
108
|
end
|
113
109
|
|
114
|
-
|
115
|
-
|
110
|
+
extends_for_instance = JSI::SchemaClasses.includes_for(jsi_node_content)
|
111
|
+
extends.merge(extends_for_instance)
|
112
|
+
extends.freeze
|
113
|
+
|
114
|
+
conflicting_modules = Set[self.class] + extends + @jsi_schemas.map(&:jsi_schema_module)
|
115
|
+
reader_modules = @jsi_schemas.map do |schema|
|
116
|
+
JSI::SchemaClasses.schema_property_reader_module(schema, conflicting_modules: conflicting_modules)
|
116
117
|
end
|
117
118
|
|
118
|
-
|
119
|
-
|
120
|
-
# in draft 4, boolean schemas are not described in the root, but on anyOf schemas on
|
121
|
-
# properties/additionalProperties and properties/additionalItems.
|
122
|
-
# these still describe schemas, despite not being described by the metaschema.
|
123
|
-
addtlPropsanyOf = metaschema_root_ptr["properties"]["additionalProperties"]["anyOf"]
|
124
|
-
addtlItemsanyOf = metaschema_root_ptr["properties"]["additionalItems"]["anyOf"]
|
119
|
+
readers = reader_modules.map(&:jsi_property_readers).inject(Set[], &:merge).freeze
|
120
|
+
define_singleton_method(:jsi_property_readers) { readers }
|
125
121
|
|
126
|
-
|
127
|
-
|
128
|
-
|
122
|
+
reader_modules.each { |reader_module| extend reader_module }
|
123
|
+
|
124
|
+
extends_for_instance.each do |m|
|
125
|
+
extend m
|
126
|
+
end
|
127
|
+
|
128
|
+
@jsi_schemas.each do |schema|
|
129
|
+
extend schema.jsi_schema_module
|
129
130
|
end
|
130
131
|
end
|
131
132
|
|
132
|
-
# Set of modules to apply to schemas
|
133
|
+
# Set of modules to apply to schemas that are instances of (described by) the meta-schema
|
133
134
|
# @return [Set<Module>]
|
134
135
|
attr_reader :schema_implementation_modules
|
135
136
|
|
136
|
-
# ptr to the root of the
|
137
|
+
# ptr to the root of the meta-schema in the jsi_document
|
137
138
|
# @return [JSI::Ptr]
|
138
139
|
attr_reader :metaschema_root_ptr
|
139
140
|
|
@@ -141,48 +142,41 @@ module JSI
|
|
141
142
|
# @return [JSI::Ptr]
|
142
143
|
attr_reader :root_schema_ptr
|
143
144
|
|
144
|
-
# JSI Schemas describing this
|
145
|
+
# JSI Schemas describing this MetaSchemaNode
|
145
146
|
# @return [JSI::SchemaSet]
|
146
147
|
attr_reader :jsi_schemas
|
147
148
|
|
148
|
-
#
|
149
|
-
#
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
def [](token, as_jsi: :auto)
|
154
|
-
if respond_to?(:to_hash)
|
155
|
-
token_in_range = jsi_node_content_hash_pubsend(:key?, token)
|
156
|
-
value = jsi_node_content_hash_pubsend(:[], token)
|
157
|
-
elsif respond_to?(:to_ary)
|
158
|
-
token_in_range = jsi_node_content_ary_pubsend(:each_index).include?(token)
|
159
|
-
value = jsi_node_content_ary_pubsend(:[], token)
|
160
|
-
else
|
161
|
-
raise(NoMethodError, "cannot subscript (using token: #{token.inspect}) from content: #{jsi_node_content.pretty_inspect.chomp}")
|
162
|
-
end
|
149
|
+
# See {Base#jsi_indicated_schemas}
|
150
|
+
# @return [JSI::SchemaSet]
|
151
|
+
def jsi_indicated_schemas
|
152
|
+
@indicated_schemas_map[]
|
153
|
+
end
|
163
154
|
|
164
|
-
|
165
|
-
|
166
|
-
|
155
|
+
# see {Base#jsi_child}
|
156
|
+
def jsi_child(token, as_jsi: )
|
157
|
+
child_node = @root_descendent_node_map[ptr: jsi_ptr[token]]
|
167
158
|
|
168
|
-
|
169
|
-
|
170
|
-
end
|
171
|
-
else
|
172
|
-
# I think I will not support Hash#default/#default_proc in this case.
|
173
|
-
nil
|
174
|
-
end
|
159
|
+
jsi_child_as_jsi(child_node.jsi_node_content, child_node.jsi_schemas, as_jsi) do
|
160
|
+
child_node
|
175
161
|
end
|
176
162
|
end
|
163
|
+
private :jsi_child
|
164
|
+
|
165
|
+
# See {Base#jsi_default_child}
|
166
|
+
def jsi_default_child(token, as_jsi: )
|
167
|
+
jsi_node_content_child(token)
|
168
|
+
end
|
169
|
+
private :jsi_default_child # internals for #[] but idk, could be public
|
177
170
|
|
178
|
-
# instantiates a new
|
171
|
+
# instantiates a new MetaSchemaNode whose instance is a modified copy of this MetaSchemaNode's instance
|
179
172
|
# @yield [Object] the node content of the instance. the block should result
|
180
173
|
# in a (nondestructively) modified copy of this.
|
181
|
-
# @return [
|
174
|
+
# @return [MetaSchemaNode] modified copy of self
|
182
175
|
def jsi_modified_copy(&block)
|
183
176
|
if jsi_ptr.root?
|
184
177
|
modified_document = jsi_ptr.modified_document_copy(jsi_document, &block)
|
185
|
-
|
178
|
+
modified_document = jsi_content_to_immutable.call(modified_document) if jsi_content_to_immutable
|
179
|
+
MetaSchemaNode.new(modified_document, **our_initialize_params)
|
186
180
|
else
|
187
181
|
modified_jsi_root_node = jsi_root_node.jsi_modified_copy do |root|
|
188
182
|
jsi_ptr.modified_document_copy(root, &block)
|
@@ -195,24 +189,37 @@ module JSI
|
|
195
189
|
# @return [Array<String>]
|
196
190
|
def jsi_object_group_text
|
197
191
|
if jsi_schemas && jsi_schemas.any?
|
198
|
-
class_n_schemas = "#{self.class} (#{jsi_schemas.map { |s| s.jsi_ptr.uri }.join(' ')})"
|
192
|
+
class_n_schemas = -"#{self.class} (#{jsi_schemas.map { |s| s.jsi_schema_module.name_from_ancestor || s.jsi_ptr.uri }.join(' ')})"
|
199
193
|
else
|
200
194
|
class_n_schemas = self.class.to_s
|
201
195
|
end
|
202
196
|
[
|
203
197
|
class_n_schemas,
|
204
|
-
is_a?(
|
205
|
-
*(jsi_node_content.respond_to?(:jsi_object_group_text) ? jsi_node_content.jsi_object_group_text :
|
206
|
-
].compact
|
198
|
+
is_a?(Schema::MetaSchema) ? "Meta-Schema" : is_a?(Schema) ? "Schema" : nil,
|
199
|
+
*(jsi_node_content.respond_to?(:jsi_object_group_text) ? jsi_node_content.jsi_object_group_text : nil),
|
200
|
+
].compact.freeze
|
207
201
|
end
|
208
202
|
|
209
|
-
#
|
203
|
+
# see {Util::Private::FingerprintHash}
|
204
|
+
# @api private
|
210
205
|
def jsi_fingerprint
|
211
|
-
{class: self.class, jsi_document: jsi_document}.merge(our_initialize_params)
|
206
|
+
{class: self.class, jsi_document: jsi_document}.merge(our_initialize_params).freeze
|
212
207
|
end
|
213
208
|
|
209
|
+
protected
|
210
|
+
|
211
|
+
attr_reader :root_descendent_node_map
|
212
|
+
|
214
213
|
private
|
215
214
|
|
215
|
+
def jsi_memomaps_initialize
|
216
|
+
if jsi_ptr.root?
|
217
|
+
@root_descendent_node_map = jsi_memomap(&method(:jsi_root_descendent_node_compute))
|
218
|
+
else
|
219
|
+
@root_descendent_node_map = @jsi_root_node.root_descendent_node_map
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
216
223
|
# note: does not include jsi_root_node
|
217
224
|
def our_initialize_params
|
218
225
|
{
|
@@ -221,22 +228,46 @@ module JSI
|
|
221
228
|
metaschema_root_ptr: metaschema_root_ptr,
|
222
229
|
root_schema_ptr: root_schema_ptr,
|
223
230
|
jsi_schema_base_uri: jsi_schema_base_uri,
|
224
|
-
|
231
|
+
jsi_schema_registry: jsi_schema_registry,
|
232
|
+
jsi_content_to_immutable: jsi_content_to_immutable,
|
233
|
+
}.freeze
|
225
234
|
end
|
226
235
|
|
227
236
|
# note: not for root node
|
228
|
-
def new_node(params)
|
229
|
-
|
237
|
+
def new_node(**params)
|
238
|
+
MetaSchemaNode.new(jsi_document, jsi_root_node: jsi_root_node, **our_initialize_params, **params)
|
230
239
|
end
|
231
240
|
|
232
|
-
def
|
233
|
-
|
241
|
+
def jsi_root_descendent_node_compute(ptr: )
|
242
|
+
#chkbug raise(Bug) unless jsi_ptr.root?
|
243
|
+
if ptr.root?
|
244
|
+
self
|
245
|
+
else
|
234
246
|
new_node(
|
235
|
-
jsi_ptr:
|
247
|
+
jsi_ptr: ptr,
|
236
248
|
jsi_schema_base_uri: jsi_resource_ancestor_uri,
|
237
|
-
jsi_root_node: jsi_root_node,
|
238
249
|
)
|
239
250
|
end
|
240
251
|
end
|
252
|
+
|
253
|
+
# @param bootstrap_schemas [Enumerable<BootstrapSchema>]
|
254
|
+
# @return [SchemaSet<MetaSchemaNode>]
|
255
|
+
def bootstrap_schemas_to_msn(bootstrap_schemas)
|
256
|
+
SchemaSet.new(bootstrap_schemas) do |bootstrap_schema|
|
257
|
+
if bootstrap_schema.jsi_ptr == jsi_ptr
|
258
|
+
self
|
259
|
+
elsif bootstrap_schema.jsi_ptr.root?
|
260
|
+
@jsi_root_node
|
261
|
+
else
|
262
|
+
new_node(
|
263
|
+
jsi_ptr: bootstrap_schema.jsi_ptr,
|
264
|
+
jsi_schema_base_uri: bootstrap_schema.jsi_schema_base_uri,
|
265
|
+
)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
241
269
|
end
|
270
|
+
|
271
|
+
# @deprecated after v0.7.0, alias of {MetaSchemaNode}
|
272
|
+
MetaschemaNode = MetaSchemaNode
|
242
273
|
end
|