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.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +101 -0
- data/LICENSE.md +613 -0
- data/README.md +303 -0
- data/docs/glossary.md +281 -0
- data/jsi.gemspec +30 -0
- data/lib/jsi/base/node.rb +373 -0
- data/lib/jsi/base.rb +738 -0
- data/lib/jsi/jsi_coder.rb +92 -0
- data/lib/jsi/metaschema.rb +6 -0
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +126 -0
- data/lib/jsi/metaschema_node.rb +262 -0
- data/lib/jsi/ptr.rb +314 -0
- data/lib/jsi/schema/application/child_application/contains.rb +25 -0
- data/lib/jsi/schema/application/child_application/draft04.rb +21 -0
- data/lib/jsi/schema/application/child_application/draft06.rb +28 -0
- data/lib/jsi/schema/application/child_application/draft07.rb +28 -0
- data/lib/jsi/schema/application/child_application/items.rb +18 -0
- data/lib/jsi/schema/application/child_application/properties.rb +25 -0
- data/lib/jsi/schema/application/child_application.rb +13 -0
- data/lib/jsi/schema/application/draft04.rb +8 -0
- data/lib/jsi/schema/application/draft06.rb +8 -0
- data/lib/jsi/schema/application/draft07.rb +8 -0
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
- data/lib/jsi/schema/application/inplace_application/draft04.rb +25 -0
- data/lib/jsi/schema/application/inplace_application/draft06.rb +26 -0
- data/lib/jsi/schema/application/inplace_application/draft07.rb +32 -0
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
- data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
- data/lib/jsi/schema/application/inplace_application/someof.rb +44 -0
- data/lib/jsi/schema/application/inplace_application.rb +14 -0
- data/lib/jsi/schema/application.rb +12 -0
- data/lib/jsi/schema/draft04.rb +13 -0
- data/lib/jsi/schema/draft06.rb +13 -0
- data/lib/jsi/schema/draft07.rb +13 -0
- data/lib/jsi/schema/issue.rb +36 -0
- data/lib/jsi/schema/ref.rb +183 -0
- data/lib/jsi/schema/schema_ancestor_node.rb +122 -0
- data/lib/jsi/schema/validation/array.rb +69 -0
- data/lib/jsi/schema/validation/const.rb +20 -0
- data/lib/jsi/schema/validation/contains.rb +25 -0
- data/lib/jsi/schema/validation/dependencies.rb +49 -0
- data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
- data/lib/jsi/schema/validation/draft04.rb +110 -0
- data/lib/jsi/schema/validation/draft06.rb +120 -0
- data/lib/jsi/schema/validation/draft07.rb +157 -0
- data/lib/jsi/schema/validation/enum.rb +25 -0
- data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
- data/lib/jsi/schema/validation/items.rb +54 -0
- data/lib/jsi/schema/validation/not.rb +20 -0
- data/lib/jsi/schema/validation/numeric.rb +121 -0
- data/lib/jsi/schema/validation/object.rb +45 -0
- data/lib/jsi/schema/validation/pattern.rb +34 -0
- data/lib/jsi/schema/validation/properties.rb +101 -0
- data/lib/jsi/schema/validation/property_names.rb +32 -0
- data/lib/jsi/schema/validation/ref.rb +40 -0
- data/lib/jsi/schema/validation/required.rb +27 -0
- data/lib/jsi/schema/validation/someof.rb +90 -0
- data/lib/jsi/schema/validation/string.rb +47 -0
- data/lib/jsi/schema/validation/type.rb +49 -0
- data/lib/jsi/schema/validation.rb +49 -0
- data/lib/jsi/schema.rb +792 -0
- data/lib/jsi/schema_classes.rb +357 -0
- data/lib/jsi/schema_registry.rb +190 -0
- data/lib/jsi/schema_set.rb +219 -0
- data/lib/jsi/simple_wrap.rb +26 -0
- data/lib/jsi/util/private/attr_struct.rb +130 -0
- data/lib/jsi/util/private/memo_map.rb +75 -0
- data/lib/jsi/util/private.rb +202 -0
- data/lib/jsi/util/typelike.rb +225 -0
- data/lib/jsi/util.rb +227 -0
- data/lib/jsi/validation/error.rb +34 -0
- data/lib/jsi/validation/result.rb +212 -0
- data/lib/jsi/validation.rb +15 -0
- data/lib/jsi/version.rb +5 -0
- data/lib/jsi.rb +105 -0
- data/lib/schemas/json-schema.org/draft-04/schema.rb +169 -0
- data/lib/schemas/json-schema.org/draft-06/schema.rb +171 -0
- data/lib/schemas/json-schema.org/draft-07/schema.rb +198 -0
- data/readme.rb +138 -0
- data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
- data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
- data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
- 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,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
|