Class: JSI::Ref
- Inherits:
-
Object
- Object
- JSI::Ref
- Includes:
- Util::FingerprintHash::Immutable
- Defined in:
- lib/jsi/ref.rb
Overview
A reference to a JSI identified by a given URI.
Direct Known Subclasses
Instance Attribute Summary collapse
- #ref ⇒ #to_str readonly
- #ref_uri ⇒ URI readonly
- #referrer ⇒ Base? readonly
- #registry ⇒ Registry? readonly
Instance Method Summary collapse
-
#initialize(ref, referrer: nil, registry: (registry_undefined = true)) ⇒ Ref
constructor
A new instance of Ref.
- #jsi_fingerprint ⇒ Object private
-
#pretty_print(q)
pretty-prints a representation of self to the given printer.
-
#resolve ⇒ JSI::Base
Resolves the target of this reference.
- #resolve_schema? ⇒ Boolean
Constructor Details
#initialize(ref, referrer: nil, registry: (registry_undefined = true)) ⇒ Ref
Returns a new instance of Ref.
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/jsi/ref.rb', line 18 def initialize(ref, referrer: nil, registry: (registry_undefined = true)) raise(ArgumentError, "ref is not a string") unless ref.respond_to?(:to_str) @ref = ref @ref_uri = Util.uri(ref, nnil: true) @referrer = referrer && resolve_schema? ? Schema.ensure_schema(referrer) : referrer @registry = !registry_undefined ? registry : referrer ? referrer.jsi_registry : JSI.registry @resolved = nil end |
Instance Attribute Details
#ref ⇒ #to_str (readonly)
30 31 32 |
# File 'lib/jsi/ref.rb', line 30 def ref @ref end |
#ref_uri ⇒ URI (readonly)
33 34 35 |
# File 'lib/jsi/ref.rb', line 33 def ref_uri @ref_uri end |
#registry ⇒ Registry? (readonly)
39 40 41 |
# File 'lib/jsi/ref.rb', line 39 def registry @registry end |
Instance Method Details
#jsi_fingerprint ⇒ Object
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.
186 187 188 189 190 191 192 193 |
# File 'lib/jsi/ref.rb', line 186 def jsi_fingerprint { class: self.class, ref: ref, referrer: referrer, registry: registry, }.freeze end |
#pretty_print(q)
This method returns an undefined value.
pretty-prints a representation of self to the given printer
180 181 182 |
# File 'lib/jsi/ref.rb', line 180 def pretty_print(q) jsi_pp_object_group(q, [self.class.name, ref].freeze) end |
#resolve ⇒ JSI::Base
Resolves the target of this reference.
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/jsi/ref.rb', line 50 def resolve return @resolved if @resolved resource_root = nil check_resource_root = proc { unless resource_root raise(ResolutionError.new([ "cannot resolve ref: #{ref}", ("from: #{referrer.pretty_inspect.chomp}" if referrer), ], uri: ref_uri)) end } ref_uri_nofrag = ref_uri.merge(fragment: nil) if ref_uri_nofrag.empty? unless referrer raise(ResolutionError.new([ "cannot resolve ref: #{ref}", "with no referrer", ], uri: ref_uri)) end # the URI only consists of a fragment (or is empty). if resolve_schema? # for a fragment pointer, resolve using Schema#resource_root_subschema on the referrer. # for a fragment anchor, use the referrer's jsi_resource_root. resource_root = referrer.jsi_resource_root # note: may be nil from bootstrap schema resolve_fragment_ptr = referrer.method(:resource_root_subschema) else resource_root = referrer.jsi_root_node resolve_fragment_ptr = resource_root.method(:jsi_descendent_node) end else # find the resource_root from the non-fragment URI. we will resolve any fragment, either pointer or anchor, from there. if ref_uri_nofrag.absolute? ref_abs_uri = ref_uri_nofrag elsif referrer && referrer.jsi_next_base_uri ref_abs_uri = referrer.jsi_next_base_uri.join(ref_uri_nofrag) else ref_abs_uri = nil end if ref_abs_uri unless registry raise(ResolutionError.new([ "could not resolve remote ref with no registry specified", "ref URI: #{ref_uri.to_s}", ("from: #{referrer.pretty_inspect.chomp}" if referrer), ], uri: ref_uri)) end resource_root = registry.find(ref_abs_uri) end if !resource_root && resolve_schema? # HAX for how google does refs and ids if referrer && referrer.jsi_document.respond_to?(:to_hash) && referrer.jsi_document['schemas'].respond_to?(:to_hash) referrer.jsi_document['schemas'].each do |k, v| if URI[v['id']] == ref_uri_nofrag resource_root = referrer.resource_root_subschema(['schemas', k]) end end end end check_resource_root.call if resolve_schema? && resource_root.is_a?(Schema) resolve_fragment_ptr = resource_root.method(:resource_root_subschema) else # Note: Schema#resource_root_subschema will reinstantiate nonschemas as schemas. # not implemented for remote refs when the resource_root is not a schema. resolve_fragment_ptr = proc { |ptr| resource_root.jsi_descendent_node(ptr) } end end fragment = ref_uri.fragment if fragment begin ptr_from_fragment = Ptr.from_fragment(fragment) rescue Ptr::PointerSyntaxError end end if ptr_from_fragment begin resolved = resolve_fragment_ptr.call(ptr_from_fragment) rescue Ptr::ResolutionError raise(ResolutionError.new([ "could not resolve pointer: #{ptr_from_fragment.pointer.inspect}", ("from: #{referrer.pretty_inspect.chomp}" if referrer), ("in resource root: #{resource_root.pretty_inspect.chomp}" if resource_root), ], uri: ref_uri)) end elsif fragment.nil? check_resource_root.call resolved = resource_root elsif resolve_schema? check_resource_root.call # find an anchor that resembles the fragment result_schemas = resource_root.jsi_anchor_subschemas(fragment) if result_schemas.size == 1 resolved = result_schemas.first elsif result_schemas.size == 0 raise(ResolutionError.new([ "could not resolve fragment: #{fragment.inspect}", "in resource root: #{resource_root.pretty_inspect.chomp}", ], uri: ref_uri)) else raise(ResolutionError.new([ "found multiple schemas for plain name fragment #{fragment.inspect}:", *result_schemas.map { |s| s.pretty_inspect.chomp }, ], uri: ref_uri)) end else raise(ResolutionError.new([ "could not resolve fragment #{fragment.inspect}. fragment must be a pointer.", ("in resource root: #{resource_root.pretty_inspect.chomp}" if resource_root), ], uri: ref_uri)) end Schema.ensure_schema(resolved) { "object identified by uri #{ref} is not a schema:" } if resolve_schema? return @resolved = resolved end |
#resolve_schema? ⇒ Boolean
42 43 44 |
# File 'lib/jsi/ref.rb', line 42 def resolve_schema? false end |