jsi 0.4.0 → 0.6.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 +1 -1
- data/CHANGELOG.md +15 -0
- data/README.md +105 -38
- data/lib/jsi/base.rb +349 -155
- data/lib/jsi/jsi_coder.rb +5 -4
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +100 -0
- data/lib/jsi/metaschema_node.rb +156 -129
- data/lib/jsi/pathed_node.rb +47 -49
- data/lib/jsi/ptr.rb +292 -0
- data/lib/jsi/schema/application/child_application/contains.rb +16 -0
- data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
- data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
- data/lib/jsi/schema/application/child_application/draft07.rb +29 -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 +40 -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 +26 -0
- data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
- data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -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 +29 -0
- data/lib/jsi/schema/application/inplace_application.rb +46 -0
- data/lib/jsi/schema/application.rb +12 -0
- data/lib/jsi/schema/draft04.rb +14 -0
- data/lib/jsi/schema/draft06.rb +14 -0
- data/lib/jsi/schema/draft07.rb +14 -0
- data/lib/jsi/schema/issue.rb +36 -0
- data/lib/jsi/schema/ref.rb +159 -0
- data/lib/jsi/schema/schema_ancestor_node.rb +119 -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/core.rb +39 -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 +112 -0
- data/lib/jsi/schema/validation/draft06.rb +122 -0
- data/lib/jsi/schema/validation/draft07.rb +159 -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 +51 -0
- data/lib/jsi/schema.rb +486 -133
- data/lib/jsi/schema_classes.rb +157 -42
- data/lib/jsi/schema_registry.rb +141 -0
- data/lib/jsi/schema_set.rb +141 -0
- data/lib/jsi/simple_wrap.rb +2 -2
- data/lib/jsi/typelike_modules.rb +52 -37
- data/lib/jsi/util/attr_struct.rb +106 -0
- data/lib/jsi/util.rb +141 -25
- data/lib/jsi/validation/error.rb +34 -0
- data/lib/jsi/validation/result.rb +210 -0
- data/lib/jsi/validation.rb +15 -0
- data/lib/jsi/version.rb +3 -1
- data/lib/jsi.rb +55 -9
- data/lib/schemas/json-schema.org/draft-04/schema.rb +8 -3
- data/lib/schemas/json-schema.org/draft-06/schema.rb +8 -3
- data/lib/schemas/json-schema.org/draft-07/schema.rb +12 -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 +69 -118
- data/.simplecov +0 -3
- data/Rakefile.rb +0 -9
- data/jsi.gemspec +0 -28
- data/lib/jsi/base/to_rb.rb +0 -128
- data/lib/jsi/json/node.rb +0 -203
- data/lib/jsi/json/pointer.rb +0 -419
- data/lib/jsi/json-schema-fragments.rb +0 -61
- data/lib/jsi/json.rb +0 -10
- data/resources/icons/AGPL-3.0.png +0 -0
- data/test/base_array_test.rb +0 -323
- data/test/base_hash_test.rb +0 -337
- data/test/base_test.rb +0 -486
- data/test/jsi_coder_test.rb +0 -85
- data/test/jsi_json_arraynode_test.rb +0 -150
- data/test/jsi_json_hashnode_test.rb +0 -132
- data/test/jsi_json_node_test.rb +0 -257
- data/test/jsi_json_pointer_test.rb +0 -102
- data/test/jsi_test.rb +0 -11
- data/test/jsi_typelike_as_json_test.rb +0 -53
- data/test/metaschema_node_test.rb +0 -19
- data/test/schema_module_test.rb +0 -21
- data/test/schema_test.rb +0 -208
- data/test/spreedly_openapi_test.rb +0 -8
- data/test/test_helper.rb +0 -97
- data/test/util_test.rb +0 -62
data/lib/jsi/jsi_coder.rb
CHANGED
|
@@ -11,7 +11,7 @@ module JSI
|
|
|
11
11
|
# `preferences_json` which is an actual json column, and `preferences_txt`
|
|
12
12
|
# which is a string:
|
|
13
13
|
#
|
|
14
|
-
# Preferences = JSI.
|
|
14
|
+
# Preferences = JSI.new_schema_module(preferences_json_schema)
|
|
15
15
|
# class Foo < ActiveRecord::Base
|
|
16
16
|
# # as a single serializer, loads a Preferences instance from a json column
|
|
17
17
|
# serialize 'preferences_json', JSI::JSICoder.new(Preferences)
|
|
@@ -25,13 +25,13 @@ module JSI
|
|
|
25
25
|
# (represented as one json object) or an array of them (represented as a json
|
|
26
26
|
# array of json objects), indicated by the keyword argument `array`.
|
|
27
27
|
class JSICoder
|
|
28
|
-
# @param schema [
|
|
29
|
-
#
|
|
28
|
+
# @param schema [#new_jsi] a Schema, SchemaSet, or JSI schema module. #load
|
|
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
|
def initialize(schema, array: false)
|
|
33
33
|
unless schema.respond_to?(:new_jsi)
|
|
34
|
-
raise(ArgumentError, "
|
|
34
|
+
raise(ArgumentError, "schema param does not respond to #new_jsi: #{schema.inspect}")
|
|
35
35
|
end
|
|
36
36
|
@schema = schema
|
|
37
37
|
@array = array
|
|
@@ -55,6 +55,7 @@ module JSI
|
|
|
55
55
|
object
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
# dumps the object for the database
|
|
58
59
|
# @param object [JSI::Base, Array<JSI::Base>, nil] the JSI or array of JSIs containing
|
|
59
60
|
# the schema instance(s)
|
|
60
61
|
# @return [Object, Array, nil] the schema instance(s) of the JSI(s), or nil if object is nil
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JSI
|
|
4
|
+
# @private
|
|
5
|
+
# internal class to bootstrap a metaschema. represents a schema without the complexity of JSI::Base. the
|
|
6
|
+
# schema is represented but schemas describing the schema are not.
|
|
7
|
+
#
|
|
8
|
+
# this class is to only be instantiated on nodes in the document that are known to be schemas.
|
|
9
|
+
# Schema#subschema and Schema#resource_root_subschema are the intended mechanisms to instantiate subschemas
|
|
10
|
+
# and resolve references. #[] and #jsi_root_node are not implemented.
|
|
11
|
+
#
|
|
12
|
+
# metaschema instance modules are attached to generated subclasses of BootstrapSchema by
|
|
13
|
+
# {SchemaClasses.bootstrap_schema_class}. that subclass is instantiated with a document and
|
|
14
|
+
# pointer, representing a schema.
|
|
15
|
+
class MetaschemaNode::BootstrapSchema
|
|
16
|
+
include Util::Memoize
|
|
17
|
+
include Util::FingerprintHash
|
|
18
|
+
include Schema::SchemaAncestorNode
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def inspect
|
|
22
|
+
if self == MetaschemaNode::BootstrapSchema
|
|
23
|
+
name
|
|
24
|
+
else
|
|
25
|
+
"#{name || MetaschemaNode::BootstrapSchema.name} (#{metaschema_instance_modules.map(&:inspect).join(', ')})"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
alias_method :to_s, :inspect
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param jsi_ptr [JSI::Ptr] pointer to the schema in the document
|
|
33
|
+
# @param jsi_document [#to_hash, #to_ary, Boolean, Object] document containing the schema
|
|
34
|
+
def initialize(
|
|
35
|
+
jsi_document,
|
|
36
|
+
jsi_ptr: Ptr[],
|
|
37
|
+
jsi_schema_base_uri: nil
|
|
38
|
+
)
|
|
39
|
+
unless respond_to?(:metaschema_instance_modules)
|
|
40
|
+
raise(TypeError, "cannot instantiate #{self.class.inspect} which has no method #metaschema_instance_modules")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
jsi_initialize_memos
|
|
44
|
+
|
|
45
|
+
self.jsi_ptr = jsi_ptr
|
|
46
|
+
self.jsi_document = jsi_document
|
|
47
|
+
self.jsi_schema_base_uri = jsi_schema_base_uri
|
|
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
|
+
# @return [String]
|
|
61
|
+
def inspect
|
|
62
|
+
"\#<#{jsi_object_group_text.join(' ')} #{schema_content.inspect}>"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# pretty-prints a representation of self to the given printer
|
|
66
|
+
# @return [void]
|
|
67
|
+
def pretty_print(q)
|
|
68
|
+
q.text '#<'
|
|
69
|
+
q.text jsi_object_group_text.join(' ')
|
|
70
|
+
q.group_sub {
|
|
71
|
+
q.nest(2) {
|
|
72
|
+
q.breakable ' '
|
|
73
|
+
q.pp schema_content
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
q.breakable ''
|
|
77
|
+
q.text '>'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @private
|
|
81
|
+
# @return [Array<String>]
|
|
82
|
+
def jsi_object_group_text
|
|
83
|
+
[
|
|
84
|
+
self.class.name || MetaschemaNode::BootstrapSchema.name,
|
|
85
|
+
"(#{metaschema_instance_modules.map(&:inspect).join(', ')})",
|
|
86
|
+
jsi_ptr.uri,
|
|
87
|
+
]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @private
|
|
91
|
+
def jsi_fingerprint
|
|
92
|
+
{
|
|
93
|
+
class: self.class,
|
|
94
|
+
jsi_ptr: @jsi_ptr,
|
|
95
|
+
jsi_document: @jsi_document,
|
|
96
|
+
metaschema_instance_modules: metaschema_instance_modules,
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
data/lib/jsi/metaschema_node.rb
CHANGED
|
@@ -1,218 +1,245 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module JSI
|
|
4
|
-
# a MetaschemaNode is a
|
|
5
|
-
# as with any PathedNode the node_ptr points to the content of a node.
|
|
4
|
+
# a MetaschemaNode is a JSI instance representing a node in a document which contains a metaschema.
|
|
6
5
|
# the root of the metaschema is pointed to by metaschema_root_ptr.
|
|
7
|
-
# the schema
|
|
6
|
+
# the schema describing the root of the document is pointed to by root_schema_ptr.
|
|
8
7
|
#
|
|
9
|
-
# like JSI::Base, this class represents an instance of a schema, an instance
|
|
10
|
-
# which may itself be a schema. unlike JSI::Base, the document containing the
|
|
11
|
-
#
|
|
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.
|
|
12
11
|
#
|
|
13
|
-
# the
|
|
14
|
-
#
|
|
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.
|
|
15
18
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# unlike with JSI::Base, the schema is not part of the class, since a metaschema
|
|
19
|
-
# needs the ability to have its schema be the instance itself.
|
|
20
|
-
#
|
|
21
|
-
# if the MetaschemaNode's schema is its self, it will be extended with JSI::Metaschema.
|
|
19
|
+
# if the MetaschemaNode's schemas include its self, it is extended with JSI::Metaschema.
|
|
22
20
|
#
|
|
23
21
|
# a MetaschemaNode is extended with JSI::Schema when it represents a schema - this is the case when
|
|
24
|
-
#
|
|
25
|
-
class MetaschemaNode
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
include
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
# @param
|
|
35
|
-
# @param
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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 metaschema_instance_modules [Enumerable<Module>] modules which implement the functionality of the
|
|
29
|
+
# schema, to be applied to every schema which is an instance of the metaschema. this must include
|
|
30
|
+
# JSI::Schema directly or indirectly. these are the {Schema#jsi_schema_instance_modules} of the
|
|
31
|
+
# metaschema.
|
|
32
|
+
# @param metaschema_root_ptr [JSI::Ptr] ptr to the root of the metaschema in the jsi_document
|
|
33
|
+
# @param root_schema_ptr [JSI::Ptr] ptr to the schema describing the root of the jsi_document
|
|
34
|
+
def initialize(
|
|
35
|
+
jsi_document,
|
|
36
|
+
jsi_ptr: Ptr[],
|
|
37
|
+
metaschema_instance_modules: ,
|
|
38
|
+
metaschema_root_ptr: Ptr[],
|
|
39
|
+
root_schema_ptr: Ptr[],
|
|
40
|
+
jsi_schema_base_uri: nil
|
|
41
|
+
)
|
|
42
|
+
jsi_initialize_memos
|
|
43
|
+
|
|
44
|
+
self.jsi_document = jsi_document
|
|
45
|
+
self.jsi_ptr = jsi_ptr
|
|
46
|
+
@metaschema_instance_modules = Util.ensure_module_set(metaschema_instance_modules)
|
|
40
47
|
@metaschema_root_ptr = metaschema_root_ptr
|
|
41
48
|
@root_schema_ptr = root_schema_ptr
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
if jsi_ptr.root? && jsi_schema_base_uri
|
|
51
|
+
raise(NotImplementedError, "unsupported jsi_schema_base_uri on metaschema document root")
|
|
52
|
+
end
|
|
53
|
+
self.jsi_schema_base_uri = jsi_schema_base_uri
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
jsi_node_content = self.jsi_node_content
|
|
56
|
+
|
|
57
|
+
if jsi_node_content.respond_to?(:to_hash)
|
|
46
58
|
extend PathedHashNode
|
|
47
|
-
|
|
59
|
+
end
|
|
60
|
+
if jsi_node_content.respond_to?(:to_ary)
|
|
48
61
|
extend PathedArrayNode
|
|
49
62
|
end
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
instance_for_schemas = jsi_document
|
|
65
|
+
bootstrap_schema_class = JSI::SchemaClasses.bootstrap_schema_class(metaschema_instance_modules)
|
|
66
|
+
root_bootstrap_schema = bootstrap_schema_class.new(
|
|
67
|
+
jsi_document,
|
|
68
|
+
jsi_ptr: root_schema_ptr,
|
|
69
|
+
jsi_schema_base_uri: nil, # supplying jsi_schema_base_uri on root bootstrap schema is not supported
|
|
70
|
+
)
|
|
71
|
+
our_bootstrap_schemas = jsi_ptr.tokens.inject(SchemaSet[root_bootstrap_schema]) do |bootstrap_schemas, tok|
|
|
72
|
+
child_instance_for_schemas = instance_for_schemas[tok]
|
|
73
|
+
bootstrap_schemas_for_instance = SchemaSet.build do |schemas|
|
|
74
|
+
bootstrap_schemas.each do |bootstrap_schema|
|
|
75
|
+
bootstrap_schema.each_child_applicator_schema(tok, instance_for_schemas) do |child_app_schema|
|
|
76
|
+
child_app_schema.each_inplace_applicator_schema(child_instance_for_schemas) do |child_inpl_app_schema|
|
|
77
|
+
schemas << child_inpl_app_schema
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
61
81
|
end
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ptr.schema_match_ptrs_to_instance(node_document, instance_for_schema)
|
|
65
|
-
end.inject(Set.new, &:|)
|
|
66
|
-
ptrs_for_instance
|
|
82
|
+
instance_for_schemas = child_instance_for_schemas
|
|
83
|
+
bootstrap_schemas_for_instance
|
|
67
84
|
end
|
|
68
85
|
|
|
69
|
-
|
|
70
|
-
if
|
|
86
|
+
our_bootstrap_schemas.each do |bootstrap_schema|
|
|
87
|
+
if bootstrap_schema.jsi_ptr == metaschema_root_ptr
|
|
88
|
+
metaschema_instance_modules.each do |metaschema_instance_module|
|
|
89
|
+
extend metaschema_instance_module
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
if bootstrap_schema.jsi_ptr == jsi_ptr
|
|
93
|
+
extend Metaschema
|
|
94
|
+
self.jsi_schema_instance_modules = metaschema_instance_modules
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
@jsi_schemas = SchemaSet.new(our_bootstrap_schemas) do |bootstrap_schema|
|
|
99
|
+
if bootstrap_schema.jsi_ptr == jsi_ptr
|
|
71
100
|
self
|
|
72
101
|
else
|
|
73
|
-
new_node(
|
|
102
|
+
new_node(
|
|
103
|
+
jsi_ptr: bootstrap_schema.jsi_ptr,
|
|
104
|
+
jsi_schema_base_uri: bootstrap_schema.jsi_schema_base_uri,
|
|
105
|
+
)
|
|
74
106
|
end
|
|
75
|
-
end
|
|
107
|
+
end
|
|
76
108
|
|
|
77
109
|
@jsi_schemas.each do |schema|
|
|
78
|
-
|
|
79
|
-
extend JSI::Schema
|
|
80
|
-
end
|
|
81
|
-
if schema.node_ptr == node_ptr
|
|
82
|
-
extend Metaschema
|
|
83
|
-
end
|
|
84
|
-
extend(JSI::SchemaClasses.accessor_module_for_schema(schema, conflicting_modules: [Metaschema, Schema, MetaschemaNode, PathedArrayNode, PathedHashNode]))
|
|
110
|
+
extend schema.jsi_schema_module
|
|
85
111
|
end
|
|
86
112
|
|
|
87
113
|
# workarounds
|
|
88
114
|
begin # draft 4 boolean schema workaround
|
|
89
115
|
# in draft 4, boolean schemas are not described in the root, but on anyOf schemas on
|
|
90
116
|
# properties/additionalProperties and properties/additionalItems.
|
|
91
|
-
#
|
|
117
|
+
# since these describe schemas, their jsi_schema_instance_modules are the metaschema_instance_modules.
|
|
92
118
|
addtlPropsanyOf = metaschema_root_ptr["properties"]["additionalProperties"]["anyOf"]
|
|
93
119
|
addtlItemsanyOf = metaschema_root_ptr["properties"]["additionalItems"]["anyOf"]
|
|
94
120
|
|
|
95
|
-
if !
|
|
96
|
-
|
|
121
|
+
if !jsi_ptr.root? && [addtlPropsanyOf, addtlItemsanyOf].include?(jsi_ptr.parent)
|
|
122
|
+
self.jsi_schema_instance_modules = metaschema_instance_modules
|
|
97
123
|
end
|
|
98
124
|
end
|
|
99
125
|
end
|
|
100
126
|
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
# ptr to the root of the metaschema in the
|
|
127
|
+
# Set of modules to apply to schemas which are instances of (described by) the metaschema
|
|
128
|
+
# @return [Set<Module>]
|
|
129
|
+
attr_reader :metaschema_instance_modules
|
|
130
|
+
|
|
131
|
+
# ptr to the root of the metaschema in the jsi_document
|
|
132
|
+
# @return [JSI::Ptr]
|
|
106
133
|
attr_reader :metaschema_root_ptr
|
|
107
|
-
|
|
134
|
+
|
|
135
|
+
# ptr to the schema of the root of the jsi_document
|
|
136
|
+
# @return [JSI::Ptr]
|
|
108
137
|
attr_reader :root_schema_ptr
|
|
109
|
-
|
|
138
|
+
|
|
139
|
+
# JSI Schemas describing this MetaschemaNode
|
|
140
|
+
# @return [JSI::SchemaSet]
|
|
110
141
|
attr_reader :jsi_schemas
|
|
111
142
|
|
|
112
|
-
#
|
|
113
|
-
|
|
114
|
-
|
|
143
|
+
# document root MetaschemaNode
|
|
144
|
+
# @return [MetaschemaNode]
|
|
145
|
+
def jsi_root_node
|
|
146
|
+
if jsi_ptr.root?
|
|
147
|
+
self
|
|
148
|
+
else
|
|
149
|
+
new_node(
|
|
150
|
+
jsi_ptr: Ptr[],
|
|
151
|
+
jsi_schema_base_uri: nil,
|
|
152
|
+
)
|
|
153
|
+
end
|
|
115
154
|
end
|
|
116
155
|
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
156
|
+
# parent MetaschemaNode
|
|
157
|
+
# @return [MetaschemaNode]
|
|
158
|
+
def jsi_parent_node
|
|
159
|
+
jsi_ptr.parent.evaluate(jsi_root_node)
|
|
120
160
|
end
|
|
121
161
|
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
|
|
162
|
+
# subscripts to return a child value identified by the given token.
|
|
163
|
+
#
|
|
164
|
+
# @param token (see JSI::Base#[])
|
|
165
|
+
# @param as_jsi (see JSI::Base#[])
|
|
166
|
+
# @return (see JSI::Base#[])
|
|
167
|
+
def [](token, as_jsi: :auto)
|
|
127
168
|
if respond_to?(:to_hash)
|
|
128
|
-
token_in_range =
|
|
129
|
-
value =
|
|
169
|
+
token_in_range = jsi_node_content_hash_pubsend(:key?, token)
|
|
170
|
+
value = jsi_node_content_hash_pubsend(:[], token)
|
|
130
171
|
elsif respond_to?(:to_ary)
|
|
131
|
-
token_in_range =
|
|
132
|
-
value =
|
|
172
|
+
token_in_range = jsi_node_content_ary_pubsend(:each_index).include?(token)
|
|
173
|
+
value = jsi_node_content_ary_pubsend(:[], token)
|
|
133
174
|
else
|
|
134
|
-
raise(NoMethodError, "cannot
|
|
175
|
+
raise(NoMethodError, "cannot subscript (using token: #{token.inspect}) from content: #{jsi_node_content.pretty_inspect.chomp}")
|
|
135
176
|
end
|
|
136
177
|
|
|
137
|
-
|
|
178
|
+
begin
|
|
138
179
|
if token_in_range
|
|
139
|
-
value_node =
|
|
180
|
+
value_node = jsi_subinstance_memos[token]
|
|
140
181
|
|
|
141
|
-
|
|
182
|
+
jsi_subinstance_as_jsi(value, value_node.jsi_schemas, as_jsi) do
|
|
142
183
|
value_node
|
|
143
|
-
else
|
|
144
|
-
value
|
|
145
184
|
end
|
|
146
185
|
else
|
|
147
186
|
# I think I will not support Hash#default/#default_proc in this case.
|
|
148
187
|
nil
|
|
149
188
|
end
|
|
150
189
|
end
|
|
151
|
-
result
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# if this MetaschemaNode is a $ref then the $ref is followed. otherwise this MetaschemaNode is returned.
|
|
155
|
-
# @return [MetaschemaNode]
|
|
156
|
-
def deref(&block)
|
|
157
|
-
node_ptr_deref do |deref_ptr|
|
|
158
|
-
return new_node(node_ptr: deref_ptr).tap(&(block || Util::NOOP))
|
|
159
|
-
end
|
|
160
|
-
return self
|
|
161
190
|
end
|
|
162
191
|
|
|
192
|
+
# instantiates a new MetaschemaNode whose instance is a modified copy of this MetaschemaNode's instance
|
|
163
193
|
# @yield [Object] the node content of the instance. the block should result
|
|
164
194
|
# in a (nondestructively) modified copy of this.
|
|
165
195
|
# @return [MetaschemaNode] modified copy of self
|
|
166
|
-
def
|
|
167
|
-
MetaschemaNode.new(
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# @return [String]
|
|
171
|
-
def inspect
|
|
172
|
-
"\#<#{object_group_text.join(' ')} #{node_content.inspect}>"
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def pretty_print(q)
|
|
176
|
-
q.text '#<'
|
|
177
|
-
q.text object_group_text.join(' ')
|
|
178
|
-
q.group_sub {
|
|
179
|
-
q.nest(2) {
|
|
180
|
-
q.breakable ' '
|
|
181
|
-
q.pp node_content
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
q.breakable ''
|
|
185
|
-
q.text '>'
|
|
196
|
+
def jsi_modified_copy(&block)
|
|
197
|
+
MetaschemaNode.new(jsi_ptr.modified_document_copy(jsi_document, &block), **our_initialize_params)
|
|
186
198
|
end
|
|
187
199
|
|
|
200
|
+
# @private
|
|
188
201
|
# @return [Array<String>]
|
|
189
|
-
def
|
|
190
|
-
if jsi_schemas.any?
|
|
191
|
-
class_n_schemas = "#{self.class} (#{jsi_schemas.map { |s| s.
|
|
202
|
+
def jsi_object_group_text
|
|
203
|
+
if jsi_schemas && jsi_schemas.any?
|
|
204
|
+
class_n_schemas = "#{self.class} (#{jsi_schemas.map { |s| s.jsi_ptr.uri }.join(' ')})"
|
|
192
205
|
else
|
|
193
206
|
class_n_schemas = self.class.to_s
|
|
194
207
|
end
|
|
195
208
|
[
|
|
196
209
|
class_n_schemas,
|
|
197
210
|
is_a?(Metaschema) ? "Metaschema" : is_a?(Schema) ? "Schema" : nil,
|
|
198
|
-
*(
|
|
211
|
+
*(jsi_node_content.respond_to?(:jsi_object_group_text) ? jsi_node_content.jsi_object_group_text : []),
|
|
199
212
|
].compact
|
|
200
213
|
end
|
|
201
214
|
|
|
202
|
-
#
|
|
215
|
+
# an opaque fingerprint of this MetaschemaNode for FingerprintHash
|
|
203
216
|
def jsi_fingerprint
|
|
204
|
-
{class: self.class,
|
|
217
|
+
{class: self.class, jsi_document: jsi_document}.merge(our_initialize_params)
|
|
205
218
|
end
|
|
206
|
-
include Util::FingerprintHash
|
|
207
219
|
|
|
208
220
|
private
|
|
209
221
|
|
|
210
222
|
def our_initialize_params
|
|
211
|
-
{
|
|
223
|
+
{
|
|
224
|
+
jsi_ptr: jsi_ptr,
|
|
225
|
+
metaschema_instance_modules: metaschema_instance_modules,
|
|
226
|
+
metaschema_root_ptr: metaschema_root_ptr,
|
|
227
|
+
root_schema_ptr: root_schema_ptr,
|
|
228
|
+
jsi_schema_base_uri: jsi_schema_base_uri,
|
|
229
|
+
}
|
|
212
230
|
end
|
|
213
231
|
|
|
214
232
|
def new_node(params)
|
|
215
|
-
MetaschemaNode.new(
|
|
233
|
+
MetaschemaNode.new(jsi_document, **our_initialize_params.merge(params))
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def jsi_subinstance_memos
|
|
237
|
+
jsi_memomap(:subinstance) do |token|
|
|
238
|
+
new_node(
|
|
239
|
+
jsi_ptr: jsi_ptr[token],
|
|
240
|
+
jsi_schema_base_uri: jsi_resource_ancestor_uri,
|
|
241
|
+
)
|
|
242
|
+
end
|
|
216
243
|
end
|
|
217
244
|
end
|
|
218
245
|
end
|