Class: Schemurai::Internal::SchemaGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/schemurai/schema_graph.rb

Defined Under Namespace

Classes: Resource

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schemas: {}, dialect: Dialect.resolve) ⇒ SchemaGraph

Returns a new instance of SchemaGraph.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/schemurai/schema_graph.rb', line 45

def initialize(schemas: {}, dialect: Dialect.resolve)
  @external_schemas = schemas.dup
  @indexed_external_schemas = nil
  @compiled_roots = {}.compare_by_identity
  @resources = {}
  @uri_registry = {}
  @nodes = []
  @nodes_by_document_location = nil
  @resolved_refs = nil
  @dynamic_anchors = {}
  # External schemas are indexed lazily, so their references are not yet
  # available to compile_node. Track conservatively from the caller.
  # Once required, dynamic scope tracking must remain enabled because all
  # evaluators sharing this graph may reach the dynamic reference.
  @dynamic_scope = !schemas.empty?
  @default_dialect = dialect
  @shareable = false
end

Instance Attribute Details

#nodesObject (readonly)

Returns the value of attribute nodes.



43
44
45
# File 'lib/schemurai/schema_graph.rb', line 43

def nodes
  @nodes
end

#resourcesObject (readonly)

Returns the value of attribute resources.



43
44
45
# File 'lib/schemurai/schema_graph.rb', line 43

def resources
  @resources
end

#uri_registryObject (readonly)

Returns the value of attribute uri_registry.



43
44
45
# File 'lib/schemurai/schema_graph.rb', line 43

def uri_registry
  @uri_registry
end

Instance Method Details

#compile(schema, base_uri: nil, dialect: @default_dialect) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/schemurai/schema_graph.rb', line 64

def compile(schema, base_uri: nil, dialect: @default_dialect)
  roots = @compiled_roots.fetch(schema) { @compiled_roots[schema] = {} }
  cache_key = [base_uri.to_s, dialect]
  roots.fetch(cache_key) do
    roots[cache_key] = compile_atomically do |changes|
      root_dialect = dialect_for(schema, dialect, changes)
      compile_document(schema, base_uri.to_s, root_dialect, changes)
    end
  end
end

#dynamic_anchor(resource, name) ⇒ Object



88
89
90
# File 'lib/schemurai/schema_graph.rb', line 88

def dynamic_anchor(resource, name)
  @dynamic_anchors.dig(resource, name)
end

#dynamic_scope?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/schemurai/schema_graph.rb', line 92

def dynamic_scope?
  @dynamic_scope
end

#make_shareableObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/schemurai/schema_graph.rb', line 96

def make_shareable
  return self if @shareable

  @external_schemas.each_key do |uri|
    index_external(strip_fragment(uri.to_s), @default_dialect)
  end

  index = 0
  while index < nodes.length
    node = nodes[index]
    schema = node.schema
    if schema.is_a?(Hash)
      ["$ref", "$recursiveRef", "$dynamicRef"].each do |keyword|
        resolve(node, schema[keyword]) if schema.key?(keyword)
      end
    end
    index += 1
  end

  @resolved_refs ||= {}
  @shareable = true
  Ractor.make_shareable(self)
end

#node_at(uri) ⇒ Object



208
209
210
# File 'lib/schemurai/schema_graph.rb', line 208

def node_at(uri)
  uri_registry[uri.to_s]
end

#resolve(node, reference) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/schemurai/schema_graph.rb', line 75

def resolve(node, reference)
  if (resolved = @resolved_refs&.[](node))&.key?(reference)
    return resolved[reference]
  end

  if @shareable
    raise ResolutionError, "reference #{reference.inspect} was not resolved before sharing"
  end

  target = resolve_uncached(node, reference)
  ((@resolved_refs ||= {})[node] ||= {})[reference] = target
end