Class: JSI::MetaschemaNode

Inherits:
Base
  • Object
show all
Defined in:
lib/jsi/metaschema_node.rb

Overview

a MetaschemaNode is a JSI instance representing a node in a document which contains a metaschema. the root of the metaschema is pointed to by metaschema_root_ptr. the schema describing the root of the document is pointed to by root_schema_ptr.

like JSI::Base's normal subclasses, this class represents an instance of a schema set, an instance which may itself be a schema. unlike JSI::Base, the document containing the instance and its schemas is the same, and a schema (the metaschema) may be an instance of itself.

unlike JSI::Base's normal subclasses, the schemas describing the instance are not part of the class. since the metaschema describes itself, attempting to construct a class from the JSI Schema Module of a schema which is itself an instance of that class results in a causality loop. instead, a MetaschemaNode calculates its #jsi_schemas and extends itself with their JSI Schema modules during initialization. the MetaschemaNode of the metaschema is extended with its own JSI Schema Module.

if the MetaschemaNode's schemas include its self, it is extended with JSI::Metaschema.

a MetaschemaNode is extended with JSI::Schema when it represents a schema - this is the case when the metaschema is one of its schemas.

Defined Under Namespace

Classes: BootstrapSchema

Instance Attribute Summary collapse

Attributes inherited from Base

#jsi_document, #jsi_ptr, #jsi_root_node

Attributes included from Schema::SchemaAncestorNode

#jsi_schema_base_uri, #jsi_schema_registry, #jsi_schema_resource_ancestors

Instance Method Summary collapse

Methods inherited from Base

#/, #[], #[]=, #as_json, #described_by?, #dup, inspect, #inspect, #jmespath_search, #jsi_ancestor_nodes, #jsi_array?, #jsi_child_as_jsi_default, #jsi_child_token_in_range?, #jsi_child_use_default_default, #jsi_descendent_node, #jsi_each_child_token, #jsi_each_descendent_node, #jsi_hash?, #jsi_node_content, #jsi_node_content_child, #jsi_parent_node, #jsi_parent_nodes, #jsi_schema_modules, #jsi_select_descendents_leaf_first, #jsi_select_descendents_node_first, #jsi_valid?, #jsi_validate, name, #pretty_print, #to_json, to_s

Methods included from Schema::SchemaAncestorNode

#jsi_anchor_subschema, #jsi_anchor_subschemas, #jsi_resource_ancestor_uri

Constructor Details

#initialize(jsi_document, jsi_ptr: Ptr[], schema_implementation_modules:, metaschema_root_ptr: Ptr[], root_schema_ptr: Ptr[], jsi_schema_base_uri: nil, jsi_schema_registry: nil, jsi_root_node: nil) ⇒ MetaschemaNode

Returns a new instance of MetaschemaNode.

Parameters:

  • jsi_document

    the document containing the metaschema

  • jsi_ptr (JSI::Ptr) (defaults to: Ptr[])

    ptr to this MetaschemaNode in jsi_document

  • schema_implementation_modules (Enumerable<Module>)

    modules which implement the functionality of the schema. these are included on the Schema#jsi_schema_module of the metaschema. they extend any schema described by the metaschema, including those in the document containing the metaschema, and the metaschema itself. see Schema#describes_schema! param schema_implementation_modules.

  • metaschema_root_ptr (JSI::Ptr) (defaults to: Ptr[])

    ptr to the root of the metaschema in the jsi_document

  • root_schema_ptr (JSI::Ptr) (defaults to: Ptr[])

    ptr to the schema describing the root of the jsi_document



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/jsi/metaschema_node.rb', line 35

def initialize(
    jsi_document,
    jsi_ptr: Ptr[],
    schema_implementation_modules: ,
    metaschema_root_ptr: Ptr[],
    root_schema_ptr: Ptr[],
    jsi_schema_base_uri: nil,
    jsi_schema_registry: nil,
    jsi_root_node: nil
)
  super(jsi_document,
    jsi_ptr: jsi_ptr,
    jsi_indicated_schemas: SchemaSet[],
    jsi_schema_base_uri: jsi_schema_base_uri,
    jsi_schema_registry: jsi_schema_registry,
    jsi_root_node: jsi_root_node,
  )

  @schema_implementation_modules = Util.ensure_module_set(schema_implementation_modules)
  @metaschema_root_ptr = metaschema_root_ptr
  @root_schema_ptr = root_schema_ptr

  if jsi_ptr.root? && jsi_schema_base_uri
    raise(NotImplementedError, "unsupported jsi_schema_base_uri on metaschema document root")
  end

  jsi_node_content = self.jsi_node_content

  extends = Set[]

  instance_for_schemas = jsi_document
  bootstrap_schema_class = JSI::SchemaClasses.bootstrap_schema_class(schema_implementation_modules)
  root_bootstrap_schema = bootstrap_schema_class.new(
    jsi_document,
    jsi_ptr: root_schema_ptr,
    jsi_schema_base_uri: nil, # supplying jsi_schema_base_uri on root bootstrap schema is not supported
  )
  our_bootstrap_indicated_schemas = jsi_ptr.tokens.inject(SchemaSet[root_bootstrap_schema]) do |bootstrap_indicated_schemas, tok|
    bootstrap_schemas = bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
    child_indicated_schemas = bootstrap_schemas.child_applicator_schemas(tok, instance_for_schemas)
    instance_for_schemas = instance_for_schemas[tok]
    child_indicated_schemas
  end
  @indicated_schemas_map = jsi_memomap { bootstrap_schemas_to_msn(our_bootstrap_indicated_schemas) }

  our_bootstrap_schemas = our_bootstrap_indicated_schemas.inplace_applicator_schemas(instance_for_schemas)
  our_bootstrap_schemas.each do |bootstrap_schema|
    if bootstrap_schema.jsi_ptr == metaschema_root_ptr
      # this is described by the metaschema, i.e. this is a schema
      extend Schema
      schema_implementation_modules.each do |schema_implementation_module|
        extend schema_implementation_module
      end
      extends += schema_implementation_modules
    end
    if bootstrap_schema.jsi_ptr == jsi_ptr
      # this is the metaschema (it is described by itself)
      extend Metaschema
      extends << Metaschema
    end
  end

  @jsi_schemas = bootstrap_schemas_to_msn(our_bootstrap_schemas)

  # note: jsi_schemas must already be set for jsi_schema_module to be used/extended
  if is_a?(Metaschema)
    describes_schema!(schema_implementation_modules)
  end

  extends_for_instance = JSI::SchemaClasses.includes_for(jsi_node_content)
  extends.merge(extends_for_instance)
  extends.freeze

  conflicting_modules = Set[self.class] + extends + @jsi_schemas.map(&:jsi_schema_module)
  reader_modules = @jsi_schemas.map do |schema|
    JSI::SchemaClasses.schema_property_reader_module(schema, conflicting_modules: conflicting_modules)
  end

  readers = reader_modules.map(&:jsi_property_readers).inject(Set[], &:merge).freeze
  define_singleton_method(:jsi_property_readers) { readers }

  reader_modules.each { |reader_module| extend reader_module }

  extends_for_instance.each do |m|
    extend m
  end

  @jsi_schemas.each do |schema|
    extend schema.jsi_schema_module
  end
end

Instance Attribute Details

#jsi_schemasJSI::SchemaSet (readonly)

JSI Schemas describing this MetaschemaNode

Returns:



141
142
143
# File 'lib/jsi/metaschema_node.rb', line 141

def jsi_schemas
  @jsi_schemas
end

#metaschema_root_ptrJSI::Ptr (readonly)

ptr to the root of the metaschema in the jsi_document

Returns:



133
134
135
# File 'lib/jsi/metaschema_node.rb', line 133

def metaschema_root_ptr
  @metaschema_root_ptr
end

#root_schema_ptrJSI::Ptr (readonly)

ptr to the schema of the root of the jsi_document

Returns:



137
138
139
# File 'lib/jsi/metaschema_node.rb', line 137

def root_schema_ptr
  @root_schema_ptr
end

#schema_implementation_modulesSet<Module> (readonly)

Set of modules to apply to schemas which are instances of (described by) the metaschema

Returns:

  • (Set<Module>)


129
130
131
# File 'lib/jsi/metaschema_node.rb', line 129

def schema_implementation_modules
  @schema_implementation_modules
end

Instance Method Details

#jsi_fingerprintObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

see Util::Private::FingerprintHash



198
199
200
# File 'lib/jsi/metaschema_node.rb', line 198

def jsi_fingerprint
  {class: self.class, jsi_document: jsi_document}.merge(our_initialize_params)
end

#jsi_indicated_schemasJSI::SchemaSet

Returns:



145
146
147
# File 'lib/jsi/metaschema_node.rb', line 145

def jsi_indicated_schemas
  @indicated_schemas_map[]
end

#jsi_modified_copy {|Object| ... } ⇒ MetaschemaNode

instantiates a new MetaschemaNode whose instance is a modified copy of this MetaschemaNode's instance

Yields:

  • (Object)

    the node content of the instance. the block should result in a (nondestructively) modified copy of this.

Returns:



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/jsi/metaschema_node.rb', line 169

def jsi_modified_copy(&block)
  if jsi_ptr.root?
    modified_document = jsi_ptr.modified_document_copy(jsi_document, &block)
    MetaschemaNode.new(modified_document, **our_initialize_params)
  else
    modified_jsi_root_node = jsi_root_node.jsi_modified_copy do |root|
      jsi_ptr.modified_document_copy(root, &block)
    end
    modified_jsi_root_node.jsi_descendent_node(jsi_ptr)
  end
end