Class: Opencdd::Entity

Inherits:
Object
  • Object
show all
Includes:
ParseHelpers
Defined in:
lib/opencdd/entity.rb,
lib/opencdd/entity/field_reader.rb,
lib/opencdd/entity/field_registry.rb,
lib/opencdd/entity/version_history.rb

Direct Known Subclasses

Klass, Property, Relation, Unit, ValueList, ValueTerm, ViewControl

Defined Under Namespace

Modules: FieldReader, FieldRegistry Classes: Dates, VersionHistory

Constant Summary collapse

META_CLASS_CODE =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ParseHelpers

brace_wrapped?, paren_wrapped?, parse_irdi_list, parse_pair_list, parse_string_list, parse_synonym_tuples, unwrap_delimiters, unwrap_parens

Constructor Details

#initialize(irdi:, properties:, schema: nil, meta_class_irdi: nil) ⇒ Entity

Returns a new instance of Entity.



83
84
85
86
87
88
89
# File 'lib/opencdd/entity.rb', line 83

def initialize(irdi:, properties:, schema: nil, meta_class_irdi: nil)
  @irdi = irdi
  @properties = properties
  @schema = schema
  @meta_class_irdi = meta_class_irdi
  @version_history = Opencdd::Entity::VersionHistory.new
end

Instance Attribute Details

#irdiObject (readonly)

Returns the value of attribute irdi.



64
65
66
# File 'lib/opencdd/entity.rb', line 64

def irdi
  @irdi
end

#meta_class_irdiObject (readonly)

Returns the value of attribute meta_class_irdi.



64
65
66
# File 'lib/opencdd/entity.rb', line 64

def meta_class_irdi
  @meta_class_irdi
end

#propertiesObject (readonly)

Returns the value of attribute properties.



64
65
66
# File 'lib/opencdd/entity.rb', line 64

def properties
  @properties
end

#schemaObject (readonly)

Returns the value of attribute schema.



64
65
66
# File 'lib/opencdd/entity.rb', line 64

def schema
  @schema
end

#source_locationObject (readonly)

Returns the value of attribute source_location.



64
65
66
# File 'lib/opencdd/entity.rb', line 64

def source_location
  @source_location
end

Class Method Details

.default_code_property_id(meta_class_irdi) ⇒ Object



79
80
81
# File 'lib/opencdd/entity.rb', line 79

def self.default_code_property_id(meta_class_irdi)
  Opencdd::MetaClasses.code_property_id_for(meta_class_irdi&.code)
end

.field(name, property_id = nil, value_kind = nil, multilingual: nil, synthetic: false, reader: nil, as: nil, &block) ⇒ Object

Declare a typed field on this entity class. Defaults for value_kind and multilingual are resolved from Opencdd::PropertyIds::REGISTRY when the property_id is known there — the REGISTRY is the SSOT for wire-format metadata, and re-declaring it here would violate DRY.

Pass an explicit value_kind to override (used when REGISTRY's kind doesn't match how the field is consumed — e.g. MDC_P023 is :identifier_ref in REGISTRY but Unit#structure uses it as a raw string).

synthetic: true for computed fields with no MDC_P### — requires a block (preferred) that returns the value. The block is evaluated via instance_exec on the entity, so it has access to private helpers without send dispatch.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/opencdd/entity.rb', line 32

def field(name, property_id = nil, value_kind = nil,
          multilingual: nil, synthetic: false, reader: nil,
          as: nil, &block)
  resolved_kind, resolved_ml = resolve_from_registry(property_id)
  Opencdd::Entity::FieldRegistry.register(
    entity_class: self,
    name: name,
    property_id: property_id,
    value_kind: value_kind || resolved_kind || :string,
    multilingual: multilingual.nil? ? resolved_ml : multilingual,
    synthetic: synthetic,
    reader: reader,
    block: block,
    json_key: as,
  )
  define_method(name) do |lang = nil|
    Opencdd::Entity::FieldReader.read(self, name, lang: lang)
  end
end

.from_row(row, schema:, meta_class_irdi:, code_property_id: nil) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/opencdd/entity.rb', line 66

def self.from_row(row, schema:, meta_class_irdi:, code_property_id: nil)
  code_property_id ||= default_code_property_id(meta_class_irdi)
  raw_code = code_property_id && row[code_property_id]
  irdi = raw_code && Opencdd::IRDI.parse(raw_code)

  props = row.each_with_object({}) do |(k, v), h|
    next if k == "__row_index__"
    h[k] = v if v
  end

  new(irdi: irdi, properties: props, schema: schema, meta_class_irdi: meta_class_irdi)
end

Instance Method Details

#[](key) ⇒ Object



166
167
168
# File 'lib/opencdd/entity.rb', line 166

def [](key)
  @properties[key.to_s]
end

#attach_source_location(loc) ⇒ Object

Attach source location (file:line) where this entity was declared. Set by Opencdd::Cddal::Builder from import/instantiation context. Nil for entities constructed from Parcel readers (which don't have a single source file).



250
251
252
253
# File 'lib/opencdd/entity.rb', line 250

def attach_source_location(loc)
  @source_location = loc
  self
end

#attach_version_history(version_history) ⇒ Object

Attach per-version provenance captured in _entity.json. Called by Opencdd::Parcel::ShardedDirReader after entity creation — the constructor doesn't take it because FlatDirReader creates entities from .xls rows without version context.



241
242
243
244
# File 'lib/opencdd/entity.rb', line 241

def attach_version_history(version_history)
  @version_history = version_history
  self
end

#codeObject Also known as: short



95
96
97
# File 'lib/opencdd/entity.rb', line 95

def code
  @irdi&.code
end

#each_propertyObject



178
179
180
181
# File 'lib/opencdd/entity.rb', line 178

def each_property
  return enum_for(:each_property) unless block_given?
  @properties.each { |k, v| yield k, v }
end

#eql?(other) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)


183
184
185
186
187
# File 'lib/opencdd/entity.rb', line 183

def eql?(other)
  other.is_a?(Opencdd::Entity) &&
    irdi == other.irdi &&
    type == other.type
end

#hashObject



189
190
191
# File 'lib/opencdd/entity.rb', line 189

def hash
  [irdi, type].hash
end

#inspectObject



195
196
197
# File 'lib/opencdd/entity.rb', line 195

def inspect
  "#<#{self.class.name} #{irdi}>"
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/opencdd/entity.rb', line 170

def key?(key)
  @properties.key?(key.to_s)
end

#keysObject



174
175
176
# File 'lib/opencdd/entity.rb', line 174

def keys
  @properties.keys
end

#read_field(name, lang: nil) ⇒ Object

Read a declared field by name. Accepts an optional lang: for multilingual fields. Returns the typed value (parsed IRDI, Array, etc.) per the field's declared value_kind.



222
223
224
# File 'lib/opencdd/entity.rb', line 222

def read_field(name, lang: nil)
  Opencdd::Entity::FieldReader.read(self, name, lang: lang)
end

#replace_code_value!(code_property_id, new_code) ⇒ Object



204
205
206
207
208
# File 'lib/opencdd/entity.rb', line 204

def replace_code_value!(code_property_id, new_code)
  return self unless code_property_id
  @properties[code_property_id.to_s] = new_code.to_s
  self
end

#replace_irdi!(new_irdi) ⇒ Object



199
200
201
202
# File 'lib/opencdd/entity.rb', line 199

def replace_irdi!(new_irdi)
  @irdi = Opencdd::IRDI === new_irdi ? new_irdi : Opencdd::IRDI.parse(new_irdi.to_s)
  self
end

#typeObject



91
92
93
# File 'lib/opencdd/entity.rb', line 91

def type
  Opencdd::Parcel::META_CLASS_TYPES[meta_class_irdi&.code]
end

#write_property!(id, value) ⇒ Object

Write a value to a property ID, routing through canonical-id alias resolution so writes are consistent with reads. Use this in preference to entity.properties[id] = value from non-infrastructure callers.



230
231
232
233
234
235
# File 'lib/opencdd/entity.rb', line 230

def write_property!(id, value)
  canonical = Opencdd::PropertyIds.canonical_id(id.to_s) || id.to_s
  base = canonical.to_s.split(".").first
  @properties[base] = value.to_s
  self
end