Class: JSON::LD::Resource

Inherits:
Object
  • Object
show all
Includes:
RDF::Enumerable
Defined in:
lib/json/ld/resource.rb

Overview

Simple Ruby reflector class to provide native access to JSON-LD objects

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node_definition, **options) ⇒ Resource

A new resource from the parsed graph

Parameters:

  • node_definition (Hash{String => Object})
  • options (Hash{Symbol => Object})

Options Hash (**options):

  • :context (String)

    Resource context, used for finding appropriate collection and JSON-LD context.

  • :clean (Boolean) — default: false
  • :compact (Boolean) — default: false

    Assume ‘node_definition` is in expanded form and compact using `context`.

  • :reconciled (Boolean) — default: !new

    node_definition is not based on Mongo IDs and must be reconciled against Mongo, or merged into another resource.

  • :new (Boolean) — default: true

    This is a new resource, not yet saved to Mongo

  • :stub (Boolean) — default: false

    This is a stand-in for another resource that has not yet been retrieved (or created) from Mongo



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/json/ld/resource.rb', line 94

def initialize(node_definition, **options)
  @context = options[:context]
  @clean = options.fetch(:clean, false)
  @new = options.fetch(:new, true)
  @reconciled = options.fetch(:reconciled, !@new)
  @resolved = false
  @attributes = if options[:compact]
    JSON::LD::API.compact(node_definition, @context)
  else
    node_definition
  end
  @id = @attributes['@id']
  @anon = @id.nil? || @id.to_s.start_with?('_:')
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *_args) ⇒ Object

Access individual fields, from subject definition



236
237
238
# File 'lib/json/ld/resource.rb', line 236

def method_missing(method, *_args)
  property(method.to_s)
end

Instance Attribute Details

#attributesHash<String => Object] Object representation of resource (readonly)

Returns Hash<String => Object] Object representation of resource.

Returns:

  • (Hash<String => Object] Object representation of resource)

    Hash<String => Object] Object representation of resource



11
12
13
# File 'lib/json/ld/resource.rb', line 11

def attributes
  @attributes
end

#contextJSON::LD::Context (readonly)

Returns Context associated with this resource.

Returns:



17
18
19
# File 'lib/json/ld/resource.rb', line 17

def context
  @context
end

#idString (readonly)

Returns ID of this resource.

Returns:

  • (String)

    ID of this resource



14
15
16
# File 'lib/json/ld/resource.rb', line 14

def id
  @id
end

Instance Method Details

#anonymous?Boolean

Anonymous resources have BNode ids or no schema:url

Returns:

  • (Boolean)


56
57
58
# File 'lib/json/ld/resource.rb', line 56

def anonymous?
  @anon
end

#clean?Boolean

Is this resource clean (i.e., saved to mongo?)

Returns:

  • (Boolean)


23
24
25
# File 'lib/json/ld/resource.rb', line 23

def clean?
  @clean
end

#deresolveHash

Reverse resolution of resource attributes. Just returns ‘attributes` if resource is unresolved. Otherwise, replaces `Resource` values with node references.

Result is expanded and re-compacted to get to normalized representation.

Returns:

  • (Hash)

    deresolved attribute hash



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
# File 'lib/json/ld/resource.rb', line 126

def deresolve
  node_definition = if resolved?
    deresolved = [].tap do |memo|
      attributes.each_pair do |prop, value|
        memo[prop] = case value
        when Resource
          { 'id' => value.id }
        when Array
          value.map do |v|
            v.is_a?(Resource) ? { 'id' => v.id } : v
          end
        else
          value
        end
      end
    end
    deresolved
  else
    attributes
  end

  compacted = nil
  JSON::LD::API.expand(node_definition, expandContext: @context) do |expanded|
    compacted = JSON::LD::API.compact(expanded, @context)
  end
  compacted.delete_if { |k, _v| k == '@context' }
end

#dirty?Boolean

Is this resource dirty (i.e., not yet saved to mongo?)

Returns:

  • (Boolean)


31
32
33
# File 'lib/json/ld/resource.rb', line 31

def dirty?
  !clean?
end

#each(&block) ⇒ Object

Enumerate over statements associated with this resource



166
167
168
# File 'lib/json/ld/resource.rb', line 166

def each(&block)
  JSON::LD::API.toRdf(attributes, expandContext: context, &block)
end

#hashInteger

Return a hash of this object, suitable for use by for ETag

Returns:

  • (Integer)


112
113
114
# File 'lib/json/ld/resource.rb', line 112

def hash
  deresolve.hash
end

#inspectObject



240
241
242
243
244
245
246
# File 'lib/json/ld/resource.rb', line 240

def inspect
  "<Resource" +
    attributes.map do |k, v|
      "\n  #{k}: #{v.inspect}"
    end.join(" ") +
    ">"
end

#new?Boolean

Is this a new resource, which has not yet been synched or created within the DB?

Returns:

  • (Boolean)


70
71
72
# File 'lib/json/ld/resource.rb', line 70

def new?
  !!@new
end

#property(prop_name) ⇒ Object

Access individual fields, from subject definition



230
231
232
# File 'lib/json/ld/resource.rb', line 230

def property(prop_name)
  @attributes.fetch(prop_name, nil)
end

#reconciled?Boolean

Has this resource been reconciled against a mongo ID?

Returns:

  • (Boolean)


39
40
41
# File 'lib/json/ld/resource.rb', line 39

def reconciled?
  @reconciled
end

#resolve(reference_map) ⇒ Resource

Update node references using the provided map. This replaces node references with Resources, either stub or instantiated.

Node references with ids not in the reference_map will cause stub resources to be added to the map.

Parameters:

  • reference_map (Hash{String => Resource})

Returns:



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/json/ld/resource.rb', line 180

def resolve(reference_map)
  return if resolved?

  def update_obj(obj, reference_map)
    case obj
    when Array
      obj.map { |o| update_obj(o, reference_map) }
    when Hash
      if node_reference?(obj)
        reference_map[obj['id']] ||= Resource.new(obj,
          context: @context_name,
          clean: false,
          stub: true)
      else
        obj.each_key do |k|
          obj[k] = update_obj(obj[k], reference_map)
        end
        obj
      end
    else
      obj
    end
  end

  # $logger.debug "resolve(0): #{attributes.inspect}"
  @attributes.each do |k, _v|
    next if %w[id type].include?(k)

    @attributes[k] = update_obj(@attributes[k], reference_map)
  end
  # $logger.debug "resolve(1): #{attributes.inspect}"
  @resolved = true
  self
end

#resolved?Boolean

Has this resource been resolved so that all references are to other Resources?

Returns:

  • (Boolean)


48
49
50
# File 'lib/json/ld/resource.rb', line 48

def resolved?
  @resolved
end

#saveBoolean

Override this method to implement save using an appropriate storage mechanism.

Save the object to the Mongo collection use Upsert to create things that don’t exist. First makes sure that the resource is valid.

Returns:

  • (Boolean)

    true or false if resource not saved

Raises:

  • (NotImplementedError)


224
225
226
# File 'lib/json/ld/resource.rb', line 224

def save
  raise NotImplementedError
end

#stub?Boolean

Is this a stub resource, which has not yet been synched or created within the DB?

Returns:

  • (Boolean)


63
64
65
# File 'lib/json/ld/resource.rb', line 63

def stub?
  !!@stub
end

#to_json(**options) ⇒ String

Serialize to JSON-LD, minus ‘@context` using a deresolved version of the attributes

Parameters:

  • options (Hash)

Returns:

  • (String)

    serizlied JSON representation of resource



160
161
162
# File 'lib/json/ld/resource.rb', line 160

def to_json(**options)
  deresolve.to_json(**options)
end

#update_obj(obj, reference_map) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/json/ld/resource.rb', line 183

def update_obj(obj, reference_map)
  case obj
  when Array
    obj.map { |o| update_obj(o, reference_map) }
  when Hash
    if node_reference?(obj)
      reference_map[obj['id']] ||= Resource.new(obj,
        context: @context_name,
        clean: false,
        stub: true)
    else
      obj.each_key do |k|
        obj[k] = update_obj(obj[k], reference_map)
      end
      obj
    end
  else
    obj
  end
end