Class: Genericode::CodeList
- Inherits:
-
Lutaml::Model::Serializable
- Object
- Lutaml::Model::Serializable
- Genericode::CodeList
- Defined in:
- lib/genericode/code_list.rb
Class Method Summary collapse
Instance Method Summary collapse
- #column_set_from_json(model, value) ⇒ Object
- #column_set_to_json(model, doc) ⇒ Object
- #key_from_json(model, value) ⇒ Object
- #key_to_json(model, doc) ⇒ Object
- #lookup(path) ⇒ Object
- #simple_code_list_from_json(model, value) ⇒ Object
- #simple_code_list_to_json(model, doc) ⇒ Object
- #valid? ⇒ Boolean
- #validate_verbose ⇒ Object
Class Method Details
.from_file(file_path) ⇒ Object
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/genericode/code_list.rb', line 20 def self.from_file(file_path) content = File.read(file_path) if file_path.end_with?(".gc") from_xml(content) elsif file_path.end_with?(".gcj") from_json(content) else raise Error, "Unsupported file format. Expected .gc or .gcj file." end end |
Instance Method Details
#column_set_from_json(model, value) ⇒ Object
40 41 42 |
# File 'lib/genericode/code_list.rb', line 40 def column_set_from_json(model, value) model.column_set = ColumnSet.of_json({ "Column" => value }) end |
#column_set_to_json(model, doc) ⇒ Object
44 45 46 |
# File 'lib/genericode/code_list.rb', line 44 def column_set_to_json(model, doc) doc["Columns"] = Column.as_json(model.column_set.column) end |
#key_from_json(model, value) ⇒ Object
48 49 50 |
# File 'lib/genericode/code_list.rb', line 48 def key_from_json(model, value) model.column_set.key = Key.of_json(value) end |
#key_to_json(model, doc) ⇒ Object
52 53 54 |
# File 'lib/genericode/code_list.rb', line 52 def key_to_json(model, doc) doc["Keys"] = Key.as_json(model.column_set.key) end |
#lookup(path) ⇒ Object
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 |
# File 'lib/genericode/code_list.rb', line 85 def lookup(path) parts = path.split(">") conditions = parts[0].split(",").to_h { |c| c.split(":") } target_column = parts[1] result = simple_code_list.row.find do |row| conditions.all? do |col, value| column = column_set.column.find { |c| c.short_name.content.downcase == col.downcase } raise Error, "Column not found: #{col}" unless column row_value = row.value.find { |v| v.column_ref == column.id }&.simple_value&.content row_value == value end end raise Error, "No matching row found for path: #{path}" unless result if target_column column = column_set.column.find { |c| c.short_name.content.downcase == target_column.downcase } raise Error, "Target column not found: #{target_column}" unless column result.value.find { |v| v.column_ref == column.id }&.simple_value&.content else result.value.to_h do |v| [column_set.column.find do |c| c.id == v.column_ref end.short_name.content, v.simple_value.content,] end end end |
#simple_code_list_from_json(model, value) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/genericode/code_list.rb', line 56 def simple_code_list_from_json(model, value) rows = value.map do |x| values = x.map do |k, v| Value.new(column_ref: k, simple_value: SimpleValue.new(content: v)) end Row.new(value: values) end model.simple_code_list = SimpleCodeList.new(row: rows) end |
#simple_code_list_to_json(model, doc) ⇒ Object
68 69 70 71 72 |
# File 'lib/genericode/code_list.rb', line 68 def simple_code_list_to_json(model, doc) doc["Codes"] = model.simple_code_list.row.map do |row| row.value.to_h { |v| [v.column_ref, v.simple_value.content] } end end |
#valid? ⇒ Boolean
116 117 118 |
# File 'lib/genericode/code_list.rb', line 116 def valid? validate_verbose.empty? end |
#validate_verbose ⇒ Object
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 177 178 179 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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/genericode/code_list.rb', line 120 def validate_verbose errors = [] # Rule 1: ColumnSet presence if column_set.nil? || column_set.column.empty? errors << { code: "MISSING_COLUMN_SET", message: "ColumnSet is missing or empty", } end # Rule 2: SimpleCodeList presence if simple_code_list.nil? || simple_code_list.row.empty? errors << { code: "MISSING_SIMPLE_CODE_LIST", message: "SimpleCodeList is missing or empty", } end # Rule 3: Unique column IDs column_ids = column_set&.column&.map(&:id) || [] if column_ids.uniq.length != column_ids.length errors << { code: "DUPLICATE_COLUMN_IDS", message: "Duplicate column IDs found" } end # Rule 4: Verify ColumnRef values simple_code_list&.row&.each_with_index do |row, index| row.value.each do |value| unless column_ids.include?(value.column_ref) errors << { code: "INVALID_COLUMN_REF", message: "Invalid ColumnRef '#{value.column_ref}' in row #{index + 1}", } end end end # Rule 5: Unique values in columns column_set&.column&.each do |col| column_values = (simple_code_list&.row&.map do |row| row.value.find { |v| v.column_ref == col.id }&.simple_value&.content end || []).compact if column_values.uniq.length != column_values.length errors << { code: "DUPLICATE_VALUES", message: "Duplicate values found in column '#{col.id}'" } end end # Rule 6: Required column values required_columns = column_set&.column&.select { |col| col.use == "required" } || [] simple_code_list&.row&.each_with_index do |row, index| required_columns.each do |col| unless row.value.any? { |v| v.column_ref == col.id && v.simple_value&.content } errors << { code: "MISSING_REQUIRED_VALUE", message: "Missing value for required column '#{col.short_name&.content}' in row #{index + 1}", } end end end # Rule 7: Data type consistency column_set&.column&.each do |col| data_type = col.data&.type simple_code_list&.row&.each_with_index do |row, index| value = row.value.find { |v| v.column_ref == col.id }&.simple_value&.content unless value_matches_type?(value, data_type) errors << { code: "INVALID_DATA_TYPE", message: "Invalid data type for column '#{col.short_name&.content}' in row #{index + 1}", } end end end # Rule 8: Valid canonical URIs if identification&.canonical_uri && !valid_uri?(identification.canonical_uri) errors << { code: "INVALID_CANONICAL_URI", message: "Invalid canonical URI" } end # Rule 19: Datatype ID validation column_set&.column&.each do |col| if col.data&.type && !valid_datatype_id?(col.data.type) errors << { code: "INVALID_DATATYPE_ID", message: "Invalid datatype ID for column '#{col.short_name&.content}'", } end # Rule 20 and 22: Complex data validation if col.data&.type == "*" && col.data&.datatype_library != "*" errors << { code: "INVALID_COMPLEX_DATA", message: "Invalid complex data configuration for column '#{col.short_name&.content}'", } end # Rule 23: Language attribute validation if col.data&.lang && col.data_restrictions&.lang errors << { code: "DUPLICATE_LANG_ATTRIBUTE", message: "Duplicate lang attribute for column '#{col.short_name&.content}'", } end end # Rule 38: Implicit column reference simple_code_list&.row&.each_with_index do |row, index| unless row.value.all?(&:column_ref) errors << { code: "MISSING_COLUMN_REF", message: "Missing explicit column reference in row #{index + 1}" } end end # Rule 39: ShortName whitespace check column_set&.column&.each do |col| if col.short_name&.content&.match?(/\s/) errors << { code: "INVALID_SHORT_NAME", message: "ShortName '#{col.short_name&.content}' contains whitespace", } end end # Rule 42 and 43: ComplexValue validation simple_code_list&.row&.each_with_index do |row, index| row.value.each do |value| next unless value.complex_value unless valid_complex_value?(value.complex_value, column_set&.column&.find { |c| c.id == value.column_ref }) errors << { code: "INVALID_COMPLEX_VALUE", message: "Invalid ComplexValue in row #{index + 1}, column '#{value.column_ref}'", } end end end errors end |