Class: Opencdd::Parcel::Sheet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/opencdd/parcel/sheet.rb

Defined Under Namespace

Classes: EntitiesProxy

Constant Summary collapse

DEFAULT_REQUIREMENT_FOR_CODE =
"KEY".freeze
DEFAULT_REQUIREMENT_OTHER =
"OPT".freeze
DEFAULT_SOURCE_LANGUAGE =
"en".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, metadata:, schema:, raw_rows:) ⇒ Sheet

Returns a new instance of Sheet.



107
108
109
110
111
112
113
114
# File 'lib/opencdd/parcel/sheet.rb', line 107

def initialize(name:, metadata:, schema:, raw_rows:)
  @name = name
  @metadata = 
  @schema = schema
  @raw_row_count = raw_rows.size
  @rows = build_rows(raw_rows)
  freeze
end

Instance Attribute Details

#metadataObject (readonly)

Returns the value of attribute metadata.



10
11
12
# File 'lib/opencdd/parcel/sheet.rb', line 10

def 
  @metadata
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/opencdd/parcel/sheet.rb', line 10

def name
  @name
end

#raw_row_countObject (readonly)

Returns the value of attribute raw_row_count.



10
11
12
# File 'lib/opencdd/parcel/sheet.rb', line 10

def raw_row_count
  @raw_row_count
end

#rowsObject (readonly)

Returns the value of attribute rows.



10
11
12
# File 'lib/opencdd/parcel/sheet.rb', line 10

def rows
  @rows
end

#schemaObject (readonly)

Returns the value of attribute schema.



10
11
12
# File 'lib/opencdd/parcel/sheet.rb', line 10

def schema
  @schema
end

Class Method Details

.default_datatype_for(property_id) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/opencdd/parcel/sheet.rb', line 56

def self.default_datatype_for(property_id)
  entry = Opencdd::PropertyIds::REGISTRY[property_id.to_s]
  return nil unless entry
  case entry.value_kind
  when :identifier_ref, :class_ref then "ICID_STRING"
  when :set_of_refs                 then "ICID_STRING"
  when :date                        then "DATE_TYPE"
  when :date_time                   then "DATE_TIME_TYPE"
  when :condition                   then "STRING_TYPE"
  else "STRING_TYPE"
  end
end

.display_name_for(property_id, _lang) ⇒ Object



50
51
52
53
54
# File 'lib/opencdd/parcel/sheet.rb', line 50

def self.display_name_for(property_id, _lang)
  entry = Opencdd::PropertyIds::REGISTRY[property_id.to_s]
  return property_id.to_s unless entry
  entry.aliases.first || property_id.to_s
end

.from_rows(rows, name: nil) ⇒ Object



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
# File 'lib/opencdd/parcel/sheet.rb', line 69

def self.from_rows(rows, name: nil)
   = Opencdd::Parcel::Metadata.new
  header_rows = []
  data_rows = []

  rows.each do |raw_row|
    row = Array(raw_row)
    first_cell = row.first&.to_s&.strip.to_s

    if first_cell.start_with?("#") && first_cell.include?(":=")
      .add(first_cell)
      next
    end

    if first_cell.start_with?("#")
      header_rows << row
      next
    end

    if row_has_data?(row)
      data_rows << row
    end
  end

  schema = Opencdd::Parcel::SheetSchema.from_header_rows(header_rows)
  new(name: name, metadata: , schema: schema, raw_rows: data_rows)
end

.row_has_data?(row) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
# File 'lib/opencdd/parcel/sheet.rb', line 97

def self.row_has_data?(row)
  row.each_with_index do |v, i|
    next if i.zero?
    next if v.nil?
    s = v.to_s.strip
    return true unless s.empty?
  end
  false
end

.scaffold(meta_class_irdi:, parcel_id:, source_language: DEFAULT_SOURCE_LANGUAGE, translation_languages: [], sheet_name: nil) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/opencdd/parcel/sheet.rb', line 12

def self.scaffold(meta_class_irdi:, parcel_id:, source_language: DEFAULT_SOURCE_LANGUAGE,
                  translation_languages: [], sheet_name: nil)
  meta = Opencdd::MetaClasses.for(meta_class_irdi.to_s) or
    raise ArgumentError, "unknown meta-class #{meta_class_irdi}"

  code_property_id = Opencdd::MetaClasses.code_property_id_for(meta.irdi)
  languages = ([source_language] + translation_languages).map(&:to_s).uniq

  columns = meta.allowed_property_ids.each_with_index.map do |property_id, idx|
    SheetSchema::Column.new(
      index: idx + 1,
      property_id: property_id,
      name_by_lang: languages.to_h { |l| [l, display_name_for(property_id, l)] },
      datatype: default_datatype_for(property_id),
      value_format: nil,
      pattern: nil,
      requirement: property_id == code_property_id ? DEFAULT_REQUIREMENT_FOR_CODE : DEFAULT_REQUIREMENT_OTHER,
    )
  end

  schema = SheetSchema.new
  columns.each do |col|
    schema.add_column(col)
  end
  schema.finalize_for_scaffold!

   = Metadata.new
  .add("#CLASS_ID := #{meta.irdi}")
  .add("#CLASS_NAME.#{source_language} := #{meta.name}")
  .add("#SOURCE_LANGUAGE := #{source_language}")
  unless translation_languages.empty?
    .add("#TRANSLATION_LANGUAGE := #{translation_languages.join(',')}")
  end

  name = sheet_name || "#{parcel_id}_#{meta.name.upcase}"
  new(name: name, metadata: , schema: schema, raw_rows: [])
end

Instance Method Details

#apply_all_default_values!Object



165
166
167
168
169
170
171
# File 'lib/opencdd/parcel/sheet.rb', line 165

def apply_all_default_values!
  @schema.columns.each do |col|
    next if col.default_value.nil?
    apply_default_values!(property_id: col.property_id)
  end
  self
end

#apply_default_values!(property_id:) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/opencdd/parcel/sheet.rb', line 153

def apply_default_values!(property_id:)
  col = @schema.find_by_property_id(property_id.to_s)
  return if col.nil? || col.default_value.nil?
  storage_key = storage_key_for(col)
  @rows.each do |row|
    current = row[storage_key]
    next if !current.nil? && !current.to_s.empty?
    row[storage_key] = col.default_value
  end
  self
end

#dup_with(name:) ⇒ Object



187
188
189
190
# File 'lib/opencdd/parcel/sheet.rb', line 187

def dup_with(name:)
  raw_rows = @rows.map { |row| row_to_array(row) }
  self.class.new(name: name, metadata: @metadata, schema: @schema, raw_rows: raw_rows)
end

#each(&block) ⇒ Object



128
129
130
# File 'lib/opencdd/parcel/sheet.rb', line 128

def each(&block)
  @rows.each(&block)
end

#entities(database = nil) ⇒ Object



149
150
151
# File 'lib/opencdd/parcel/sheet.rb', line 149

def entities(database = nil)
  EntitiesProxy.new(self, database)
end

#firstObject



141
142
143
# File 'lib/opencdd/parcel/sheet.rb', line 141

def first
  @rows.first
end

#lastObject



145
146
147
# File 'lib/opencdd/parcel/sheet.rb', line 145

def last
  @rows.last
end

#merge_rows_from(other) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/opencdd/parcel/sheet.rb', line 173

def merge_rows_from(other)
  unless meta_codes_match?(meta_class_irdi, other.meta_class_irdi)
    raise ArgumentError,
          "meta-class mismatch: #{meta_class_irdi} vs #{other.meta_class_irdi}"
  end
  other.rows.each do |src|
    new_row = src.reject { |k, _| k == "__row_index__" }
    next if new_row.empty?
    new_row["__row_index__"] = @rows.size
    @rows << new_row
  end
  self
end

#meta_class_codeObject



120
121
122
# File 'lib/opencdd/parcel/sheet.rb', line 120

def meta_class_code
  @metadata.meta_class_code
end

#meta_class_irdiObject



116
117
118
# File 'lib/opencdd/parcel/sheet.rb', line 116

def meta_class_irdi
  @metadata.meta_class_irdi
end

#sizeObject Also known as: count, length



134
135
136
# File 'lib/opencdd/parcel/sheet.rb', line 134

def size
  @rows.size
end

#typeObject



124
125
126
# File 'lib/opencdd/parcel/sheet.rb', line 124

def type
  @metadata.type
end