jsi-dev 0.0.0.pre.kramdown

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/CHANGELOG.md +101 -0
  4. data/LICENSE.md +613 -0
  5. data/README.md +303 -0
  6. data/docs/glossary.md +281 -0
  7. data/jsi.gemspec +30 -0
  8. data/lib/jsi/base/node.rb +373 -0
  9. data/lib/jsi/base.rb +738 -0
  10. data/lib/jsi/jsi_coder.rb +92 -0
  11. data/lib/jsi/metaschema.rb +6 -0
  12. data/lib/jsi/metaschema_node/bootstrap_schema.rb +126 -0
  13. data/lib/jsi/metaschema_node.rb +262 -0
  14. data/lib/jsi/ptr.rb +314 -0
  15. data/lib/jsi/schema/application/child_application/contains.rb +25 -0
  16. data/lib/jsi/schema/application/child_application/draft04.rb +21 -0
  17. data/lib/jsi/schema/application/child_application/draft06.rb +28 -0
  18. data/lib/jsi/schema/application/child_application/draft07.rb +28 -0
  19. data/lib/jsi/schema/application/child_application/items.rb +18 -0
  20. data/lib/jsi/schema/application/child_application/properties.rb +25 -0
  21. data/lib/jsi/schema/application/child_application.rb +13 -0
  22. data/lib/jsi/schema/application/draft04.rb +8 -0
  23. data/lib/jsi/schema/application/draft06.rb +8 -0
  24. data/lib/jsi/schema/application/draft07.rb +8 -0
  25. data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
  26. data/lib/jsi/schema/application/inplace_application/draft04.rb +25 -0
  27. data/lib/jsi/schema/application/inplace_application/draft06.rb +26 -0
  28. data/lib/jsi/schema/application/inplace_application/draft07.rb +32 -0
  29. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
  30. data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
  31. data/lib/jsi/schema/application/inplace_application/someof.rb +44 -0
  32. data/lib/jsi/schema/application/inplace_application.rb +14 -0
  33. data/lib/jsi/schema/application.rb +12 -0
  34. data/lib/jsi/schema/draft04.rb +13 -0
  35. data/lib/jsi/schema/draft06.rb +13 -0
  36. data/lib/jsi/schema/draft07.rb +13 -0
  37. data/lib/jsi/schema/issue.rb +36 -0
  38. data/lib/jsi/schema/ref.rb +183 -0
  39. data/lib/jsi/schema/schema_ancestor_node.rb +122 -0
  40. data/lib/jsi/schema/validation/array.rb +69 -0
  41. data/lib/jsi/schema/validation/const.rb +20 -0
  42. data/lib/jsi/schema/validation/contains.rb +25 -0
  43. data/lib/jsi/schema/validation/dependencies.rb +49 -0
  44. data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
  45. data/lib/jsi/schema/validation/draft04.rb +110 -0
  46. data/lib/jsi/schema/validation/draft06.rb +120 -0
  47. data/lib/jsi/schema/validation/draft07.rb +157 -0
  48. data/lib/jsi/schema/validation/enum.rb +25 -0
  49. data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
  50. data/lib/jsi/schema/validation/items.rb +54 -0
  51. data/lib/jsi/schema/validation/not.rb +20 -0
  52. data/lib/jsi/schema/validation/numeric.rb +121 -0
  53. data/lib/jsi/schema/validation/object.rb +45 -0
  54. data/lib/jsi/schema/validation/pattern.rb +34 -0
  55. data/lib/jsi/schema/validation/properties.rb +101 -0
  56. data/lib/jsi/schema/validation/property_names.rb +32 -0
  57. data/lib/jsi/schema/validation/ref.rb +40 -0
  58. data/lib/jsi/schema/validation/required.rb +27 -0
  59. data/lib/jsi/schema/validation/someof.rb +90 -0
  60. data/lib/jsi/schema/validation/string.rb +47 -0
  61. data/lib/jsi/schema/validation/type.rb +49 -0
  62. data/lib/jsi/schema/validation.rb +49 -0
  63. data/lib/jsi/schema.rb +792 -0
  64. data/lib/jsi/schema_classes.rb +357 -0
  65. data/lib/jsi/schema_registry.rb +190 -0
  66. data/lib/jsi/schema_set.rb +219 -0
  67. data/lib/jsi/simple_wrap.rb +26 -0
  68. data/lib/jsi/util/private/attr_struct.rb +130 -0
  69. data/lib/jsi/util/private/memo_map.rb +75 -0
  70. data/lib/jsi/util/private.rb +202 -0
  71. data/lib/jsi/util/typelike.rb +225 -0
  72. data/lib/jsi/util.rb +227 -0
  73. data/lib/jsi/validation/error.rb +34 -0
  74. data/lib/jsi/validation/result.rb +212 -0
  75. data/lib/jsi/validation.rb +15 -0
  76. data/lib/jsi/version.rb +5 -0
  77. data/lib/jsi.rb +105 -0
  78. data/lib/schemas/json-schema.org/draft-04/schema.rb +169 -0
  79. data/lib/schemas/json-schema.org/draft-06/schema.rb +171 -0
  80. data/lib/schemas/json-schema.org/draft-07/schema.rb +198 -0
  81. data/readme.rb +138 -0
  82. data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
  83. data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
  84. data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
  85. metadata +155 -0
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ # this is an ActiveRecord serialization coder intended to serialize between
5
+ # JSON-compatible objects on the database side, and a JSI instance loaded on
6
+ # the model attribute.
7
+ #
8
+ # on its own this coder is useful with a JSON database column. in order to
9
+ # serialize further to a string of JSON, or to YAML, the gem `arms` allows
10
+ # coders to be chained together. for example, for a table `foos` and a column
11
+ # `preferences_json` which is an actual json column, and `preferences_txt`
12
+ # which is a string:
13
+ #
14
+ # Preferences = JSI.new_schema_module(preferences_json_schema)
15
+ # class Foo < ActiveRecord::Base
16
+ # # as a single serializer, loads a Preferences instance from a json column
17
+ # serialize 'preferences_json', JSI::JSICoder.new(Preferences)
18
+ #
19
+ # # for a text column, arms_serialize will go from JSI to JSON-compatible
20
+ # # objects to a string. the symbol `:jsi` is a shortcut for JSI::JSICoder.
21
+ # arms_serialize 'preferences_txt', [:jsi, Preferences], :json
22
+ # end
23
+ #
24
+ # the column data may be either a single instance of the schema class
25
+ # (represented as one json object) or an array of them (represented as a json
26
+ # array of json objects), indicated by the keyword argument `array`.
27
+ class JSICoder
28
+ # @param schema [#new_jsi] a Schema, SchemaSet, or JSI schema module. #load
29
+ # will instantiate column data using the JSI schemas represented.
30
+ # @param array [Boolean] whether the dumped data represent one instance of the schema,
31
+ # or an array of them. note that it may be preferable to simply use an array schema.
32
+ # @param jsi_opt [Hash] keyword arguments to pass to {Schema#new_jsi} when loading
33
+ def initialize(schema, array: false, jsi_opt: {})
34
+ unless schema.respond_to?(:new_jsi)
35
+ raise(ArgumentError, "schema param does not respond to #new_jsi: #{schema.inspect}")
36
+ end
37
+ @schema = schema
38
+ @array = array
39
+ @jsi_opt = jsi_opt
40
+ end
41
+
42
+ # loads the database column to JSI instances of our schema
43
+ #
44
+ # @param data [Object, Array, nil] the dumped schema instance(s) of the JSI(s)
45
+ # @return [JSI::Base, Array<JSI::Base>, nil] the JSI or JSIs containing the schema
46
+ # instance(s), or nil if data is nil
47
+ def load(data)
48
+ return nil if data.nil?
49
+
50
+ if @array
51
+ unless data.respond_to?(:to_ary)
52
+ raise TypeError, "expected array-like column data; got: #{data.class}: #{data.inspect}"
53
+ end
54
+ data.to_ary.map { |el| load_object(el) }
55
+ else
56
+ load_object(data)
57
+ end
58
+ end
59
+
60
+ # dumps the object for the database
61
+ # @param object [JSI::Base, Array<JSI::Base>, nil] the JSI or array of JSIs containing
62
+ # the schema instance(s)
63
+ # @return [Object, Array, nil] the schema instance(s) of the JSI(s), or nil if object is nil
64
+ def dump(object)
65
+ return nil if object.nil?
66
+
67
+ if @array
68
+ unless object.respond_to?(:to_ary)
69
+ raise(TypeError, "expected array-like attribute; got: #{object.class}: #{object.inspect}")
70
+ end
71
+ object.to_ary.map do |el|
72
+ dump_object(el)
73
+ end
74
+ else
75
+ dump_object(object)
76
+ end
77
+ end
78
+
79
+ private
80
+ # @param data [Object]
81
+ # @return [JSI::Base]
82
+ def load_object(data)
83
+ @schema.new_jsi(data, **@jsi_opt)
84
+ end
85
+
86
+ # @param object [JSI::Base, Object]
87
+ # @return [Object]
88
+ def dump_object(object)
89
+ JSI::Util.as_json(object)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ module Metaschema
5
+ end
6
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ # internal class to bootstrap a metaschema. represents a schema without the complexity of JSI::Base. the
5
+ # schema is represented but schemas describing the schema are not.
6
+ #
7
+ # this class is to only be instantiated on nodes in the document that are known to be schemas.
8
+ # Schema#subschema and Schema#resource_root_subschema are the intended mechanisms to instantiate subschemas
9
+ # and resolve references. #[] and #jsi_root_node are not implemented.
10
+ #
11
+ # schema implementation modules are included on generated subclasses of BootstrapSchema by
12
+ # {SchemaClasses.bootstrap_schema_class}. that subclass is instantiated with a document and
13
+ # pointer, representing a schema.
14
+ #
15
+ # @api private
16
+ class MetaschemaNode::BootstrapSchema
17
+ include Util::FingerprintHash
18
+ include Schema::SchemaAncestorNode
19
+ include Schema
20
+
21
+ class << self
22
+ def inspect
23
+ if self == MetaschemaNode::BootstrapSchema
24
+ name
25
+ else
26
+ -"#{name || MetaschemaNode::BootstrapSchema.name} (#{schema_implementation_modules.map(&:inspect).join(', ')})"
27
+ end
28
+ end
29
+
30
+ alias_method :to_s, :inspect
31
+ end
32
+
33
+ # @param jsi_ptr [JSI::Ptr] pointer to the schema in the document
34
+ # @param jsi_document [#to_hash, #to_ary, Boolean, Object] document containing the schema
35
+ def initialize(
36
+ jsi_document,
37
+ jsi_ptr: Ptr[],
38
+ jsi_schema_base_uri: nil
39
+ )
40
+ raise(Bug, "no #schema_implementation_modules") unless respond_to?(:schema_implementation_modules)
41
+
42
+ super()
43
+
44
+ self.jsi_ptr = jsi_ptr
45
+ self.jsi_document = jsi_document
46
+ self.jsi_schema_base_uri = jsi_schema_base_uri
47
+ self.jsi_schema_resource_ancestors = Util::EMPTY_ARY
48
+ end
49
+
50
+ # document containing the schema content
51
+ attr_reader :jsi_document
52
+
53
+ # JSI::Ptr pointing to this schema within the document
54
+ attr_reader :jsi_ptr
55
+
56
+ def jsi_node_content
57
+ jsi_ptr.evaluate(jsi_document)
58
+ end
59
+
60
+ # overrides {Schema#subschema}
61
+ def subschema(subptr)
62
+ self.class.new(
63
+ jsi_document,
64
+ jsi_ptr: jsi_ptr + subptr,
65
+ jsi_schema_base_uri: jsi_resource_ancestor_uri,
66
+ )
67
+ end
68
+
69
+ # overrides {Schema#resource_root_subschema}
70
+ def resource_root_subschema(ptr)
71
+ # BootstrapSchema does not track jsi_schema_resource_ancestors used by Schema#schema_resource_root;
72
+ # resource_root_subschema is always relative to the document root.
73
+ # BootstrapSchema also does not implement jsi_root_node or #[]. we instantiate the ptr directly
74
+ # rather than as a subschema from the root.
75
+ self.class.new(
76
+ jsi_document,
77
+ jsi_ptr: Ptr.ary_ptr(ptr),
78
+ jsi_schema_base_uri: nil,
79
+ )
80
+ end
81
+
82
+ # @return [String]
83
+ def inspect
84
+ -"\#<#{jsi_object_group_text.join(' ')} #{schema_content.inspect}>"
85
+ end
86
+
87
+ alias_method :to_s, :inspect
88
+
89
+ # pretty-prints a representation of self to the given printer
90
+ # @return [void]
91
+ def pretty_print(q)
92
+ q.text '#<'
93
+ q.text jsi_object_group_text.join(' ')
94
+ q.group_sub {
95
+ q.nest(2) {
96
+ q.breakable ' '
97
+ q.pp schema_content
98
+ }
99
+ }
100
+ q.breakable ''
101
+ q.text '>'
102
+ end
103
+
104
+ # @private
105
+ # @return [Array<String>]
106
+ def jsi_object_group_text
107
+ [
108
+ self.class.name || MetaschemaNode::BootstrapSchema.name,
109
+ -"(#{schema_implementation_modules.map(&:inspect).join(', ')})",
110
+ jsi_ptr.uri,
111
+ ]
112
+ end
113
+
114
+ # see {Util::Private::FingerprintHash}
115
+ # @api private
116
+ def jsi_fingerprint
117
+ {
118
+ class: self.class,
119
+ jsi_ptr: @jsi_ptr,
120
+ jsi_document: @jsi_document,
121
+ jsi_schema_base_uri: jsi_schema_base_uri,
122
+ schema_implementation_modules: schema_implementation_modules,
123
+ }
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,262 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ # a MetaschemaNode is a JSI instance representing a node in a document which contains a metaschema.
5
+ # the root of the metaschema is pointed to by metaschema_root_ptr.
6
+ # the schema describing the root of the document is pointed to by root_schema_ptr.
7
+ #
8
+ # like JSI::Base's normal subclasses, this class represents an instance of a schema set, an instance
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 metaschema) may be an instance of itself.
11
+ #
12
+ # unlike JSI::Base's normal subclasses, the schemas describing the instance are not part of the class.
13
+ # since the metaschema describes itself, attempting to construct a class from the JSI Schema Module of a
14
+ # schema which is itself an instance of that class results in a causality loop.
15
+ # instead, a MetaschemaNode calculates its {#jsi_schemas} and extends itself with their JSI Schema
16
+ # modules during initialization.
17
+ # the MetaschemaNode of the metaschema is extended with its own JSI Schema Module.
18
+ #
19
+ # if the MetaschemaNode's schemas include its self, it is extended with JSI::Metaschema.
20
+ #
21
+ # a MetaschemaNode is extended with JSI::Schema when it represents a schema - this is the case when
22
+ # the metaschema is one of its schemas.
23
+ class MetaschemaNode < Base
24
+ autoload :BootstrapSchema, 'jsi/metaschema_node/bootstrap_schema'
25
+
26
+ # @param jsi_document the document containing the metaschema
27
+ # @param jsi_ptr [JSI::Ptr] ptr to this MetaschemaNode in jsi_document
28
+ # @param schema_implementation_modules [Enumerable<Module>] modules which implement the functionality
29
+ # of the schema. these are included on the {Schema#jsi_schema_module} of the metaschema.
30
+ # they extend any schema described by the metaschema, including those in the document containing
31
+ # the metaschema, and the metaschema itself.
32
+ # see {Schema#describes_schema!} param `schema_implementation_modules`.
33
+ # @param metaschema_root_ptr [JSI::Ptr] ptr to the root of the metaschema in the jsi_document
34
+ # @param root_schema_ptr [JSI::Ptr] ptr to the schema describing the root of the jsi_document
35
+ def initialize(
36
+ jsi_document,
37
+ jsi_ptr: Ptr[],
38
+ schema_implementation_modules: ,
39
+ metaschema_root_ptr: Ptr[],
40
+ root_schema_ptr: Ptr[],
41
+ jsi_schema_base_uri: nil,
42
+ jsi_schema_registry: nil,
43
+ jsi_root_node: nil
44
+ )
45
+ super(jsi_document,
46
+ jsi_ptr: jsi_ptr,
47
+ jsi_indicated_schemas: SchemaSet[],
48
+ jsi_schema_base_uri: jsi_schema_base_uri,
49
+ jsi_schema_registry: jsi_schema_registry,
50
+ jsi_root_node: jsi_root_node,
51
+ )
52
+
53
+ @schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules)
54
+ @metaschema_root_ptr = metaschema_root_ptr
55
+ @root_schema_ptr = root_schema_ptr
56
+
57
+ if jsi_ptr.root? && jsi_schema_base_uri
58
+ raise(NotImplementedError, "unsupported jsi_schema_base_uri on metaschema document root")
59
+ end
60
+
61
+ jsi_node_content = self.jsi_node_content
62
+
63
+ extends = Set[]
64
+
65
+ instance_for_schemas = jsi_document
66
+ bootstrap_schema_class = JSI::SchemaClasses.bootstrap_schema_class(schema_implementation_modules)
67
+ root_bootstrap_schema = bootstrap_schema_class.new(
68
+ jsi_document,
69
+ jsi_ptr: root_schema_ptr,
70
+ jsi_schema_base_uri: nil, # supplying jsi_schema_base_uri on root bootstrap schema is not supported
71
+ )
72
+ our_bootstrap_indicated_schemas = jsi_ptr.tokens.inject(SchemaSet[root_bootstrap_schema]) do |bootstrap_indicated_schemas, tok|
73
+ bootstrap_schemas = bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
74
+ child_indicated_schemas = bootstrap_schemas.child_applicator_schemas(tok, instance_for_schemas)
75
+ instance_for_schemas = instance_for_schemas[tok]
76
+ child_indicated_schemas
77
+ end
78
+ @indicated_schemas_map = jsi_memomap { bootstrap_schemas_to_msn(our_bootstrap_indicated_schemas) }
79
+
80
+ our_bootstrap_schemas = our_bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
81
+ our_bootstrap_schemas.each do |bootstrap_schema|
82
+ if bootstrap_schema.jsi_ptr == metaschema_root_ptr
83
+ # this is described by the metaschema, i.e. this is a schema
84
+ extend Schema
85
+ schema_implementation_modules.each do |schema_implementation_module|
86
+ extend schema_implementation_module
87
+ end
88
+ extends += schema_implementation_modules
89
+ end
90
+ if bootstrap_schema.jsi_ptr == jsi_ptr
91
+ # this is the metaschema (it is described by itself)
92
+ extend Metaschema
93
+ extends << Metaschema
94
+ end
95
+ end
96
+
97
+ @jsi_schemas = bootstrap_schemas_to_msn(our_bootstrap_schemas)
98
+
99
+ # note: jsi_schemas must already be set for jsi_schema_module to be used/extended
100
+ if is_a?(Metaschema)
101
+ describes_schema!(schema_implementation_modules)
102
+ end
103
+
104
+ extends_for_instance = JSI::SchemaClasses.includes_for(jsi_node_content)
105
+ extends.merge(extends_for_instance)
106
+ extends.freeze
107
+
108
+ conflicting_modules = Set[self.class] + extends + @jsi_schemas.map(&:jsi_schema_module)
109
+ reader_modules = @jsi_schemas.map do |schema|
110
+ JSI::SchemaClasses.schema_property_reader_module(schema, conflicting_modules: conflicting_modules)
111
+ end
112
+
113
+ readers = reader_modules.map(&:jsi_property_readers).inject(Set[], &:merge).freeze
114
+ define_singleton_method(:jsi_property_readers) { readers }
115
+
116
+ reader_modules.each { |reader_module| extend reader_module }
117
+
118
+ extends_for_instance.each do |m|
119
+ extend m
120
+ end
121
+
122
+ @jsi_schemas.each do |schema|
123
+ extend schema.jsi_schema_module
124
+ end
125
+ end
126
+
127
+ # Set of modules to apply to schemas which are instances of (described by) the metaschema
128
+ # @return [Set<Module>]
129
+ attr_reader :schema_implementation_modules
130
+
131
+ # ptr to the root of the metaschema in the jsi_document
132
+ # @return [JSI::Ptr]
133
+ attr_reader :metaschema_root_ptr
134
+
135
+ # ptr to the schema of the root of the jsi_document
136
+ # @return [JSI::Ptr]
137
+ attr_reader :root_schema_ptr
138
+
139
+ # JSI Schemas describing this MetaschemaNode
140
+ # @return [JSI::SchemaSet]
141
+ attr_reader :jsi_schemas
142
+
143
+ # See {Base#jsi_indicated_schemas}
144
+ # @return [JSI::SchemaSet]
145
+ def jsi_indicated_schemas
146
+ @indicated_schemas_map[]
147
+ end
148
+
149
+ # see {Base#jsi_child}
150
+ def jsi_child(token, as_jsi: )
151
+ child_node = @root_descendent_node_map[ptr: jsi_ptr[token]]
152
+
153
+ jsi_child_as_jsi(jsi_node_content_child(token), child_node.jsi_schemas, as_jsi) do
154
+ child_node
155
+ end
156
+ end
157
+ private :jsi_child
158
+
159
+ # See {Base#jsi_default_child}
160
+ def jsi_default_child(token, as_jsi: )
161
+ jsi_node_content_child(token)
162
+ end
163
+ private :jsi_default_child # internals for #[] but idk, could be public
164
+
165
+ # instantiates a new MetaschemaNode whose instance is a modified copy of this MetaschemaNode's instance
166
+ # @yield [Object] the node content of the instance. the block should result
167
+ # in a (nondestructively) modified copy of this.
168
+ # @return [MetaschemaNode] modified copy of self
169
+ def jsi_modified_copy(&block)
170
+ if jsi_ptr.root?
171
+ modified_document = jsi_ptr.modified_document_copy(jsi_document, &block)
172
+ MetaschemaNode.new(modified_document, **our_initialize_params)
173
+ else
174
+ modified_jsi_root_node = jsi_root_node.jsi_modified_copy do |root|
175
+ jsi_ptr.modified_document_copy(root, &block)
176
+ end
177
+ modified_jsi_root_node.jsi_descendent_node(jsi_ptr)
178
+ end
179
+ end
180
+
181
+ # @private
182
+ # @return [Array<String>]
183
+ def jsi_object_group_text
184
+ if jsi_schemas && jsi_schemas.any?
185
+ class_n_schemas = -"#{self.class} (#{jsi_schemas.map { |s| s.jsi_schema_module.name_from_ancestor || s.jsi_ptr.uri }.join(' ')})"
186
+ else
187
+ class_n_schemas = self.class.to_s
188
+ end
189
+ [
190
+ class_n_schemas,
191
+ is_a?(Metaschema) ? "Metaschema" : is_a?(Schema) ? "Schema" : nil,
192
+ *(jsi_node_content.respond_to?(:jsi_object_group_text) ? jsi_node_content.jsi_object_group_text : nil),
193
+ ].compact
194
+ end
195
+
196
+ # see {Util::Private::FingerprintHash}
197
+ # @api private
198
+ def jsi_fingerprint
199
+ {class: self.class, jsi_document: jsi_document}.merge(our_initialize_params)
200
+ end
201
+
202
+ protected
203
+
204
+ attr_reader :root_descendent_node_map
205
+
206
+ private
207
+
208
+ def jsi_memomaps_initialize
209
+ if jsi_ptr.root?
210
+ @root_descendent_node_map = jsi_memomap(key_by: proc { |i| i[:ptr] }, &method(:jsi_root_descendent_node_compute))
211
+ else
212
+ @root_descendent_node_map = @jsi_root_node.root_descendent_node_map
213
+ end
214
+ end
215
+
216
+ # note: does not include jsi_root_node
217
+ def our_initialize_params
218
+ {
219
+ jsi_ptr: jsi_ptr,
220
+ schema_implementation_modules: schema_implementation_modules,
221
+ metaschema_root_ptr: metaschema_root_ptr,
222
+ root_schema_ptr: root_schema_ptr,
223
+ jsi_schema_base_uri: jsi_schema_base_uri,
224
+ jsi_schema_registry: jsi_schema_registry,
225
+ }
226
+ end
227
+
228
+ # note: not for root node
229
+ def new_node(**params)
230
+ MetaschemaNode.new(jsi_document, jsi_root_node: jsi_root_node, **our_initialize_params, **params)
231
+ end
232
+
233
+ def jsi_root_descendent_node_compute(ptr: )
234
+ #chkbug raise(Bug) unless jsi_ptr.root?
235
+ if ptr.root?
236
+ self
237
+ else
238
+ new_node(
239
+ jsi_ptr: ptr,
240
+ jsi_schema_base_uri: jsi_resource_ancestor_uri,
241
+ )
242
+ end
243
+ end
244
+
245
+ # @param bootstrap_schemas [Enumerable<BootstrapSchema>]
246
+ # @return [SchemaSet<MetaschemaNode>]
247
+ def bootstrap_schemas_to_msn(bootstrap_schemas)
248
+ SchemaSet.new(bootstrap_schemas) do |bootstrap_schema|
249
+ if bootstrap_schema.jsi_ptr == jsi_ptr
250
+ self
251
+ elsif bootstrap_schema.jsi_ptr.root?
252
+ @jsi_root_node
253
+ else
254
+ new_node(
255
+ jsi_ptr: bootstrap_schema.jsi_ptr,
256
+ jsi_schema_base_uri: bootstrap_schema.jsi_schema_base_uri,
257
+ )
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end