labimotion 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labimotion/apis/labimotion_api.rb +3 -1
  3. data/lib/labimotion/apis/labimotion_hub_api.rb +83 -10
  4. data/lib/labimotion/apis/standard_api.rb +2 -1
  5. data/lib/labimotion/apis/standard_layer_api.rb +17 -4
  6. data/lib/labimotion/apis/vocabulary_api.rb +20 -6
  7. data/lib/labimotion/constants.rb +7 -0
  8. data/lib/labimotion/entities/dataset_entity.rb +1 -0
  9. data/lib/labimotion/entities/element_entity.rb +0 -1
  10. data/lib/labimotion/entities/klass_revision_entity.rb +5 -9
  11. data/lib/labimotion/entities/properties_entity.rb +41 -102
  12. data/lib/labimotion/entities/segment_entity.rb +2 -0
  13. data/lib/labimotion/entities/vocabulary_entity.rb +12 -3
  14. data/lib/labimotion/helpers/element_helpers.rb +1 -2
  15. data/lib/labimotion/helpers/generic_helpers.rb +1 -6
  16. data/lib/labimotion/helpers/param_helpers.rb +16 -0
  17. data/lib/labimotion/libs/converter.rb +1 -0
  18. data/lib/labimotion/libs/data/layer/StdDataset.json +212 -0
  19. data/lib/labimotion/libs/data/vocab/System.json +1 -1
  20. data/lib/labimotion/libs/export_dataset.rb +98 -343
  21. data/lib/labimotion/libs/nmr_mapper.rb +247 -204
  22. data/lib/labimotion/libs/template_hub.rb +28 -10
  23. data/lib/labimotion/models/concerns/generic_klass_revisions.rb +0 -1
  24. data/lib/labimotion/models/concerns/generic_revisions.rb +0 -3
  25. data/lib/labimotion/models/concerns/klass_revision.rb +23 -0
  26. data/lib/labimotion/models/dataset_klasses_revision.rb +4 -1
  27. data/lib/labimotion/models/element.rb +0 -3
  28. data/lib/labimotion/models/element_klasses_revision.rb +3 -2
  29. data/lib/labimotion/models/segment_klasses_revision.rb +4 -1
  30. data/lib/labimotion/models/template_submission.rb +52 -0
  31. data/lib/labimotion/utils/utils.rb +0 -21
  32. data/lib/labimotion/version.rb +1 -1
  33. data/lib/labimotion.rb +3 -3
  34. metadata +5 -6
  35. data/lib/labimotion/libs/data/mapper/Chemwiki.json +0 -236
  36. data/lib/labimotion/libs/data/mapper/Source.json +0 -78
  37. data/lib/labimotion/libs/dataset_builder.rb +0 -70
  38. data/lib/labimotion/utils/mapper_utils.rb +0 -169
@@ -1,258 +1,301 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'labimotion/libs/dataset_builder'
4
3
  require 'labimotion/version'
5
- require 'labimotion/utils/mapper_utils'
6
4
  require 'labimotion/utils/utils'
7
5
 
8
6
  module Labimotion
9
7
  ## NmrMapper
10
8
  class NmrMapper
11
- # Constants specific to NMR mapping
12
- module Constants
13
- # Duplicate fields that need special handling
14
- DUP_FIELDS = %w[time version].freeze
15
-
16
- # Field groups for different processing stages
17
- FG_FINALIZE = %w[set.temperature general.date general.time software.Name software.Version].freeze
18
- FG_SYSTEM = %w[general.creator sample_details.label sample_details.id].freeze
19
-
20
- # Valid NMR nuclei types
21
- OBSERVED = %w[1H 13C].freeze
22
-
23
- # OLS terms for different NMR types
24
- module OlsTerms
25
- NMR_1H = 'CHMO:0000593'
26
- NMR_13C = 'CHMO:0000595'
9
+ def self.process_ds(id, current_user = {})
10
+ att = Attachment.find_by(id: id, con_state: Labimotion::ConState::NMR)
11
+ return if att.nil?
12
+
13
+ result = is_brucker_binary(id)
14
+ if result[:is_bagit] == true
15
+ att.update_column(:con_state, Labimotion::ConState::CONVERTED)
16
+ Labimotion::Converter.metadata(id, current_user)
17
+ Labimotion::ConState::COMPLETED
18
+ elsif result[:metadata] == nil
19
+ Labimotion::ConState::NONE
20
+ else
21
+ ds = Container.find_by(id: att.attachable_id)
22
+ return if ds.nil? || ds.parent&.container_type != 'analysis'
23
+
24
+ data = process(att, id, result[:metadata])
25
+ generate_ds(id, att.attachable_id, data, current_user)
26
+ Labimotion::ConState::COMPLETED
27
27
  end
28
28
  end
29
29
 
30
- class << self
31
- def process_ds(id, current_user = {})
32
- att = find_attachment(id)
33
- return Labimotion::ConState::NONE if att.nil?
30
+ def self.is_brucker_binary(id)
31
+ att = Attachment.find_by(id: id, con_state: Labimotion::ConState::NMR)
32
+ return if att.nil?
33
+
34
+ if att&.attachment_attacher&.file&.url
35
+ Zip::File.open(att.attachment_attacher.file.url) do |zip_file|
36
+ zip_file.each do |entry|
37
+ if entry.name.include?('/pdata/') && entry.name.include?('parm.txt')
38
+ metadata = entry.get_input_stream.read.force_encoding('UTF-8')
39
+ return { is_bagit: false, metadata: metadata }
40
+ elsif entry.name.include?('metadata/') && entry.name.include?('converter.json')
41
+ return { is_bagit: true, metadata: nil }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ { is_bagit: false, metadata: nil }
47
+ end
34
48
 
35
- result = process(att)
36
- return Labimotion::ConState::NONE if result.nil?
49
+ def self.process(att, id, content)
50
+ return if att.nil? || content.nil?
37
51
 
38
- handle_process_result(result, att, id, current_user)
52
+ lines = content.split("\n").reject(&:empty?)
53
+ metadata = {}
54
+ lines.map do |ln|
55
+ arr = ln.split(/\s+/)
56
+ metadata[arr[0]] = arr[1..-1].join(' ') if arr.length > 1
39
57
  end
58
+ ols = 'CHMO:0000593' if metadata['NUC1'] == '1H'
59
+ ols = 'CHMO:0000595' if metadata['NUC1'] == '13C'
60
+
61
+ { content: { metadata: metadata, ols: ols } }
62
+ # if content.present? && att.present?
63
+ # Labimotion::NmrMapper.ts('write', att.attachable_id,
64
+ # content: { metadata: metadata, ols: ols })
65
+ # end
66
+ end
40
67
 
41
- def process(att)
42
- config = Labimotion::MapperUtils.load_brucker_config
43
- return if config.nil?
44
-
45
- attacher = att&.attachment_attacher
46
- extracted_data = Labimotion::MapperUtils.extract_data_from_zip(attacher&.file&.url, config['sourceMap'])
47
- return if extracted_data.nil?
68
+ def self.fetch_content(id)
69
+ atts = Attachment.where(attachable_id: id)
70
+ return if atts.nil?
48
71
 
49
- extracted_data[:parameters] = config['sourceMap']['parameters']
50
- extracted_data
72
+ atts.each do |att|
73
+ content = Labimotion::NmrMapper.ts('read', att.id)
74
+ return content if content.present?
51
75
  end
76
+ end
52
77
 
53
- def generate_ds(_id, cid, data, current_user = {}, element = nil)
54
- return if data.nil? || cid.nil?
55
78
 
56
- obj = Labimotion::NmrMapper.build_ds(cid, data[:content])
57
- return if obj.nil? || obj[:ols].nil?
79
+ def self.generate_ds(id, cid, data, current_user = {})
80
+ return if data.nil? || cid.nil?
58
81
 
59
- Labimotion::NmrMapper.update_ds(cid, obj, current_user, element)
60
- end
82
+ obj = Labimotion::NmrMapper.build_ds(cid, data[:content])
83
+ return if obj.nil? || obj[:ols].nil?
61
84
 
62
- def update_ds(_cid, obj, current_user, element)
63
- dataset = obj[:dataset]
64
- dataset.properties = process_prop(obj, current_user, element)
65
- dataset.save!
66
- end
85
+ Labimotion::NmrMapper.update_ds_1h(cid, obj, current_user) if obj[:ols] == 'CHMO:0000593'
86
+ Labimotion::NmrMapper.update_ds_1h(cid, obj, current_user) if obj[:ols] == 'CHMO:0000595'
87
+ end
67
88
 
68
- def build_ds(id, content)
69
- ds = find_container(id)
70
- return if ds.nil? || content.nil?
89
+ def self.update_ds_13c(id, obj)
90
+ # dataset = obj[:dataset]
91
+ # metadata = obj[:metadata]
92
+ # new_prop = dataset.properties
71
93
 
72
- Labimotion::DatasetBuilder.build(ds, content)
73
- end
94
+ # dataset.properties = new_prop
95
+ # dataset.save!
96
+ end
74
97
 
75
- private
98
+ def self.set_data(prop, field, idx, layer_name, field_name, value)
99
+ return if field['field'] != field_name || value&.empty?
76
100
 
77
- def finalize_ds(new_prop)
78
- Constants::FG_FINALIZE.each do |field_path|
79
- field = Labimotion::Utils.find_field(new_prop, field_path)
80
- next unless field
101
+ field['value'] = value
102
+ prop[Labimotion::Prop::LAYERS][layer_name][Labimotion::Prop::FIELDS][idx] = field
103
+ prop
104
+ end
81
105
 
82
- update_finalized_field(field)
106
+ def self.update_ds_1h(id, obj, current_user)
107
+ dataset = obj[:dataset]
108
+ metadata = obj[:metadata]
109
+ new_prop = dataset.properties
110
+ new_prop.dig(Labimotion::Prop::LAYERS, 'general', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
111
+ # new_prop = set_data(new_prop, fi, idx, 'general', 'title', metadata['NAME'])
112
+ if fi['field'] == 'title' && metadata['NAME'].present?
113
+ ## fi['label'] = fi['label']
114
+ fi['value'] = metadata['NAME']
115
+ fi['device'] = metadata['NAME']
116
+ fi['dkey'] = 'NAME'
117
+ new_prop[Labimotion::Prop::LAYERS]['general'][Labimotion::Prop::FIELDS][idx] = fi
83
118
  end
84
- new_prop
85
- end
86
119
 
87
- def sys_to_ds(new_prop, element, current_user)
88
- Constants::FG_SYSTEM.each do |field_path|
89
- field = Labimotion::Utils.find_field(new_prop, field_path)
90
- next unless field
91
-
92
- update_system_field(field, current_user, element)
120
+ if fi['field'] == 'date' && metadata['Date_'].present?
121
+ ## fi['label'] = fi['label']
122
+ fi['value'] = metadata['Date_']
123
+ fi['device'] = metadata['Date_']
124
+ fi['dkey'] = 'Date_'
125
+ new_prop[Labimotion::Prop::LAYERS]['general'][Labimotion::Prop::FIELDS][idx] = fi
93
126
  end
94
- new_prop
95
- end
96
-
97
- def params_to_ds(obj, new_prop)
98
- metadata = obj[:metadata]
99
- parameters = obj[:parameters]
100
127
 
101
- parameters.each do |param_key, field_path|
102
- next if skip_parameter?(metadata, param_key)
103
-
104
- update_param_field(new_prop, field_path, param_key, metadata)
128
+ if fi['field'] == 'time' && metadata['Time'].present?
129
+ ## fi['label'] = fi['label']
130
+ fi['value'] = metadata['Time']
131
+ fi['device'] = metadata['Time']
132
+ fi['dkey'] = 'Time'
133
+ new_prop[Labimotion::Prop::LAYERS]['general'][Labimotion::Prop::FIELDS][idx] = fi
105
134
  end
106
- new_prop
107
- end
108
-
109
- def process_prop(obj, current_user, element)
110
- new_prop = obj[:dataset].properties
111
- new_prop
112
- .then { |prop| params_to_ds(obj, prop) }
113
- .then { |prop| sys_to_ds(prop, element, current_user) }
114
- .then { |prop| finalize_ds(prop) }
115
- .then { |prop| Labimotion::VocabularyHandler.update_vocabularies(prop, current_user, element) }
116
- end
117
-
118
- def find_attachment(id)
119
- Attachment.find_by(id: id, con_state: Labimotion::ConState::NMR)
120
- end
121
135
 
122
- def handle_process_result(result, att, id, current_user)
123
- if result[:is_bagit]
124
- handle_bagit_result(att, id, current_user)
125
- elsif invalid_metadata?(result)
126
- Labimotion::ConState::NONE
127
- else
128
- handle_nmr_result(result, att, current_user)
136
+ if fi['field'] == 'creator' && current_user.present?
137
+ ## fi['label'] = fi['label']
138
+ fi['value'] = current_user.name
139
+ new_prop[Labimotion::Prop::LAYERS]['general'][Labimotion::Prop::FIELDS][idx] = fi
129
140
  end
130
141
  end
131
-
132
- def handle_bagit_result(att, id, current_user)
133
- att.update_column(:con_state, Labimotion::ConState::CONVERTED)
134
- Labimotion::Converter.metadata(id, current_user)
135
- Labimotion::ConState::COMPLETED
136
- end
137
-
138
- def invalid_metadata?(result)
139
- result[:metadata].nil? ||
140
- Constants::OBSERVED.exclude?(result[:metadata]['NUC1'])
141
- end
142
-
143
- def handle_nmr_result(result, att, current_user)
144
- ds = find_container(att.attachable_id)
145
- return Labimotion::ConState::NONE unless valid_container?(ds)
146
-
147
- prepare_mapper_result(ds, result, current_user)
148
- Labimotion::ConState::COMPLETED
149
- end
150
-
151
- def find_container(cid)
152
- Container.find_by(id: cid)
153
- end
154
-
155
- def valid_container?(container)
156
- container.present? &&
157
- container.parent&.container_type == 'analysis' &&
158
- container.root_element.present?
159
- end
160
-
161
- def prepare_mapper_result(container, result, current_user)
162
- metadata = result[:metadata]
163
- ols = determine_ols_term(metadata['NUC1'])
164
-
165
- data = {
166
- content: {
167
- metadata: metadata,
168
- ols: ols,
169
- parameters: result[:parameters]
170
- }
171
- }
172
-
173
- generate_ds(nil, container.id, data, current_user, container.root_element)
174
- end
175
-
176
- def determine_ols_term(nuc1)
177
- case nuc1
178
- when '1H' then Constants::OlsTerms::NMR_1H
179
- when '13C' then Constants::OlsTerms::NMR_13C
142
+ element = Container.find(id)&.root_element
143
+ element.present? && element&.class&.name == 'Sample' && new_prop.dig(Labimotion::Prop::LAYERS, 'sample_details',
144
+ Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
145
+ if fi['field'] == 'label'
146
+ fi['value'] = element.short_label
147
+ new_prop[Labimotion::Prop::LAYERS]['sample_details'][Labimotion::Prop::FIELDS][idx] = fi
180
148
  end
181
- end
182
-
183
- def skip_parameter?(metadata, param_key)
184
- metadata[param_key.to_s].blank? &&
185
- Constants::DUP_FIELDS.exclude?(param_key.to_s.downcase)
186
- end
187
-
188
- def update_param_field(properties, field_path, param_key, metadata)
189
- field = Labimotion::Utils.find_field(properties, field_path)
190
- return unless field
191
-
192
- update_field_value(field, param_key, metadata)
193
- update_field_extend(field, param_key, metadata)
194
- end
195
-
196
- def update_duplicate_field(field_name, metadata)
197
- case field_name
198
- when 'time' then metadata['DATE']
199
- when 'Version' then metadata['TITLE']
149
+ if fi['field'] == 'id'
150
+ fi['value'] = element.id
151
+ new_prop[Labimotion::Prop::LAYERS]['sample_details'][Labimotion::Prop::FIELDS][idx] = fi
200
152
  end
201
153
  end
202
154
 
203
- def update_field_value(field, param_key, metadata)
204
- field['value'] = format_field_value(field, param_key, metadata)
205
- rescue StandardError => e
206
- Rails.logger.error "Error converting value for #{param_key}: #{e.message}"
207
- field['value'] = ''
208
- end
209
-
210
- def format_field_value(field, param_key, metadata)
211
- if field['type'] == 'integer'
212
- Integer(metadata[param_key.to_s])
213
- elsif Constants::DUP_FIELDS.include?(param_key.to_s.downcase)
214
- update_duplicate_field(field['field'], metadata)
215
- else
216
- metadata[param_key.to_s]
155
+ new_prop.dig(Labimotion::Prop::LAYERS, 'instrument', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
156
+ if fi['field'] == 'instrument' && metadata['INSTRUM'].present?
157
+ ## fi['label'] = fi['label']
158
+ fi['value'] = metadata['INSTRUM']
159
+ fi['device'] = metadata['INSTRUM']
160
+ fi['dkey'] = 'INSTRUM'
161
+ new_prop[Labimotion::Prop::LAYERS]['instrument'][Labimotion::Prop::FIELDS][idx] = fi
217
162
  end
218
163
  end
219
164
 
220
- def update_finalized_field(field)
221
- case field['field']
222
- when 'temperature'
223
- field['value_system'] = 'K'
224
- when 'date', 'time'
225
- field['value'] = Labimotion::MapperUtils.format_timestamp(field['value'], field['field'])
226
- when 'Name'
227
- field['value'] = 'TopSpin' if field['value'].to_s.include?('TopSpin')
228
- when 'Version'
229
- field['value'] = field['value'].to_s.split('TopSpin').last.strip if field['value'].to_s.include?('TopSpin')
165
+ new_prop.dig(Labimotion::Prop::LAYERS, 'equipment', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
166
+ if fi['field'] == 'probehead' && metadata['PROBHD'].present?
167
+ ## fi['label'] = fi['label']
168
+ fi['value'] = metadata['PROBHD']
169
+ fi['device'] = metadata['PROBHD']
170
+ fi['dkey'] = 'PROBHD'
171
+ new_prop[Labimotion::Prop::LAYERS]['equipment'][Labimotion::Prop::FIELDS][idx] = fi
230
172
  end
231
173
  end
232
174
 
233
- def update_system_field(field, current_user, element)
234
- field['value'] = determine_field_value(field['field'], current_user, element)
175
+ new_prop.dig(Labimotion::Prop::LAYERS, 'sample_preparation', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
176
+ if fi['field'] == 'solvent' && metadata['SOLVENT'].present?
177
+ ## fi['label'] = fi['label']
178
+ fi['value'] = metadata['SOLVENT']
179
+ fi['device'] = metadata['SOLVENT']
180
+ fi['dkey'] = 'SOLVENT'
181
+ fi['value'] = 'chloroform-D1 (CDCl3)' if metadata['SOLVENT'] == 'CDCl3'
182
+ new_prop[Labimotion::Prop::LAYERS]['sample_preparation'][Labimotion::Prop::FIELDS][idx] = fi
183
+ end
235
184
  end
236
185
 
237
- def determine_field_value(field_name, current_user, element)
238
- case field_name
239
- when 'creator'
240
- current_user&.name if current_user.present?
241
- when 'label', 'id'
242
- get_sample_value(field_name, element)
186
+ new_prop.dig(Labimotion::Prop::LAYERS, 'set', Labimotion::Prop::FIELDS)&.each_with_index do |fi, idx|
187
+ if fi['field'] == 'temperature' && metadata['TE'].present?
188
+ ## fi['label'] = fi['label']
189
+ fi['value'] = metadata['TE'].split(/\s+/).first
190
+ fi['device'] = metadata['TE']
191
+ fi['dkey'] = 'TE'
192
+ fi['value_system'] = metadata['TE'].split(/\s+/).last
193
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
194
+ end
195
+ if fi['field'] == 'ns' && metadata['NS'].present?
196
+ ## fi['label'] = fi['label']
197
+ fi['value'] = metadata['NS']
198
+ fi['device'] = metadata['NS']
199
+ fi['dkey'] = 'NS'
200
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
201
+ end
202
+ if fi['field'] == 'PULPROG' && metadata['PULPROG'].present?
203
+ ## fi['label'] = fi['label']
204
+ fi['value'] = metadata['PULPROG']
205
+ fi['device'] = metadata['PULPROG']
206
+ fi['dkey'] = 'PULPROG'
207
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
208
+ end
209
+ if fi['field'] == 'td' && metadata['TD'].present?
210
+ ## fi['label'] = fi['label']
211
+ fi['value'] = metadata['TD']
212
+ fi['device'] = metadata['TD']
213
+ fi['dkey'] = 'TD'
214
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
215
+ end
216
+ if fi['field'] == 'done' && metadata['D1'].present?
217
+ ## fi['label'] = fi['label']
218
+ fi['value'] = metadata['D1']
219
+ fi['device'] = metadata['D1']
220
+ fi['dkey'] = 'D1'
221
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
222
+ end
223
+ if fi['field'] == 'sf' && metadata['SF'].present?
224
+ ## fi['label'] = fi['label']
225
+ fi['value'] = metadata['SF']
226
+ fi['device'] = metadata['SF']
227
+ fi['dkey'] = 'SF'
228
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
229
+ end
230
+ if fi['field'] == 'sfoone' && metadata['SFO1'].present?
231
+ ## fi['label'] = fi['label']
232
+ fi['value'] = metadata['SFO1']
233
+ fi['device'] = metadata['SFO1']
234
+ fi['dkey'] = 'SFO1'
235
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
236
+ end
237
+ if fi['field'] == 'sfotwo' && metadata['SFO2'].present?
238
+ ## fi['label'] = fi['label']
239
+ fi['value'] = metadata['SFO2']
240
+ fi['device'] = metadata['SFO2']
241
+ fi['dkey'] = 'SFO2'
242
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
243
+ end
244
+ if fi['field'] == 'nucone' && metadata['NUC1'].present?
245
+ ## fi['label'] = fi['label']
246
+ fi['value'] = metadata['NUC1']
247
+ fi['device'] = metadata['NUC1']
248
+ fi['dkey'] = 'NUC1'
249
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
250
+ end
251
+ if fi['field'] == 'nuctwo' && metadata['NUC2'].present?
252
+ ## fi['label'] = fi['label']
253
+ fi['value'] = metadata['NUC2']
254
+ fi['device'] = metadata['NUC2']
255
+ fi['dkey'] = 'NUC2'
256
+ new_prop[Labimotion::Prop::LAYERS]['set'][Labimotion::Prop::FIELDS][idx] = fi
243
257
  end
244
258
  end
259
+ new_prop = Labimotion::VocabularyHandler.update_vocabularies(new_prop, current_user, element)
260
+ dataset.properties = new_prop
261
+ dataset.save!
262
+ end
245
263
 
246
- def get_sample_value(field_name, element)
247
- return unless element.present? && element.is_a?(Sample)
264
+ def self.ts(method, identifier, params = nil)
265
+ Rails.cache.send(method, "#{Labimotion::NmrMapper.new.class.name}#{identifier}", params)
266
+ end
248
267
 
249
- field_name == 'label' ? element.short_label : element.id
250
- end
268
+ def self.clean(id)
269
+ Labimotion::NmrMapper.ts('delete', id)
270
+ end
251
271
 
252
- def update_field_extend(field, param_key, metadata)
253
- field['device'] = metadata[param_key.to_s]
254
- field['dkey'] = param_key.to_s
255
- end
272
+ def self.build_ds(id, content)
273
+ ds = Container.find_by(id: id)
274
+ return if ds.nil? || content.nil?
275
+
276
+ ols = content[:ols]
277
+ metadata = content[:metadata]
278
+
279
+ return if ols.nil? || metadata.nil?
280
+
281
+ klass = Labimotion::DatasetKlass.find_by(ols_term_id: ols)
282
+ return if klass.nil?
283
+
284
+ uuid = SecureRandom.uuid
285
+ props = klass.properties_release
286
+ props['uuid'] = uuid
287
+ props['pkg'] = Labimotion::Utils.pkg(props['pkg'])
288
+ props['klass'] = 'Dataset'
289
+ dataset = Labimotion::Dataset.create!(
290
+ uuid: uuid,
291
+ dataset_klass_id: klass.id,
292
+ element_type: 'Container',
293
+ element_id: ds.id,
294
+ properties: props,
295
+ properties_release: klass.properties_release,
296
+ klass_uuid: klass.uuid,
297
+ )
298
+ { dataset: dataset, metadata: metadata, ols: ols }
256
299
  end
257
300
  end
258
301
  end
@@ -5,9 +5,6 @@ require 'uri'
5
5
  require 'json'
6
6
  require 'date'
7
7
 
8
- # rubocop: disable Metrics/AbcSize
9
- # rubocop: disable Metrics/MethodLength
10
-
11
8
  module Labimotion
12
9
  ## TemplateHub
13
10
  class TemplateHub
@@ -18,12 +15,11 @@ module Labimotion
18
15
  "#{url}api/v1/labimotion_hub/#{api_name}"
19
16
  end
20
17
 
21
-
22
18
  def self.header(opt = {})
23
19
  opt || { timeout: 10, headers: { 'Content-Type' => 'text/json' } }
24
20
  end
25
21
 
26
- def self.handle_response(oat, response) # rubocop: disable Metrics/PerceivedComplexity
22
+ def self.handle_response(oat, response)
27
23
  begin
28
24
  response&.success? ? 'OK' : 'ERROR'
29
25
  rescue StandardError => e
@@ -56,10 +52,32 @@ module Labimotion
56
52
  Labimotion.log_exception(e)
57
53
  error!('Cannot connect to Chemotion Repository', 401)
58
54
  end
55
+
56
+ def self.send_to_central_hub(klass, template, metadata, origin)
57
+ body = {
58
+ template_klass: klass,
59
+ template: template,
60
+ metadata: metadata,
61
+ origin: origin
62
+ }
63
+ response = HTTParty.post(
64
+ Labimotion::TemplateHub.uri('template_submissions'),
65
+ headers: {
66
+ 'Content-Type' => 'application/json',
67
+ 'X-Origin-URL' => origin
68
+ },
69
+ body: body.to_json,
70
+ timeout: 10
71
+ )
72
+
73
+ if [200, 201].include?(response.code)
74
+ parsed_response = JSON.parse(response.body)
75
+ return { mc: 'ss00', data: { id: parsed_response['id'] } }
76
+ end
77
+ { mc: 'se00', msg: "HTTP #{response.code}: #{response.message}", data: {} }
78
+ rescue StandardError => e
79
+ Labimotion.log_exception(e)
80
+ { mc: 'se00', msg: "Connection failure: #{e.message}", data: {} }
81
+ end
59
82
  end
60
83
  end
61
-
62
- # rubocop: enable Metrics/AbcSize
63
- # rubocop: enable Metrics/MethodLength
64
- # rubocop: enable Metrics/ClassLength
65
- # rubocop: enable Metrics/CyclomaticComplexity
@@ -43,7 +43,6 @@ module Labimotion
43
43
  released_by: released_by,
44
44
  uuid: uuid,
45
45
  version: version,
46
- created_by: updated_by,
47
46
  properties_release: properties_release,
48
47
  released_at: released_at
49
48
  }
@@ -8,8 +8,6 @@ module Labimotion
8
8
  after_create :create_vault
9
9
  after_update :save_to_vault
10
10
  before_destroy :delete_attachments
11
-
12
- ## attr_accessor :user_for_revision
13
11
  end
14
12
 
15
13
  def create_vault
@@ -21,7 +19,6 @@ module Labimotion
21
19
  uuid: uuid,
22
20
  klass_uuid: klass_uuid,
23
21
  properties: properties,
24
- ## created_by: user_for_revision&.id,
25
22
  properties_release: properties_release
26
23
  }
27
24
  attributes["#{Labimotion::Utils.element_name_dc(self.class.name)}_id"] = id
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ # Shared concern for all Klass Revision models
5
+ # Provides a unified interface to access the parent klass object
6
+ module KlassRevision
7
+ extend ActiveSupport::Concern
8
+
9
+ # Returns the associated klass object (ElementKlass, SegmentKlass, or DatasetKlass)
10
+ def klass
11
+ return element_klass if respond_to?(:element_klass)
12
+ return segment_klass if respond_to?(:segment_klass)
13
+ return dataset_klass if respond_to?(:dataset_klass)
14
+
15
+ nil
16
+ end
17
+
18
+ # Increments the submitted counter and saves the record
19
+ def increment_submitted!
20
+ increment!(:submitted)
21
+ end
22
+ end
23
+ end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'labimotion/models/concerns/klass_revision'
4
+
3
5
  module Labimotion
4
6
  class DatasetKlassesRevision < ApplicationRecord
5
7
  self.table_name = :dataset_klasses_revisions
6
8
  acts_as_paranoid
7
- has_one :dataset_klass, class_name: 'Labimotion::DatasetKlass'
9
+ include KlassRevision
10
+ belongs_to :dataset_klass, class_name: 'Labimotion::DatasetKlass'
8
11
  end
9
12
  end
@@ -58,9 +58,6 @@ module Labimotion
58
58
  after_create :update_counter
59
59
  before_destroy :delete_attachment
60
60
 
61
- def user_labels
62
- tag&.taggable_data&.fetch('user_labels', nil)
63
- end
64
61
 
65
62
  def attachments
66
63
  Attachment.where(attachable_id: self.id, attachable_type: self.class.name)
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'labimotion/models/concerns/workflow'
4
+ require 'labimotion/models/concerns/klass_revision'
4
5
 
5
6
  module Labimotion
6
7
  class ElementKlassesRevision < ApplicationRecord
7
8
  acts_as_paranoid
8
9
  self.table_name = :element_klasses_revisions
9
10
  include Workflow
10
- has_one :element_klass, class_name: 'Labimotion::ElementKlass'
11
-
11
+ include KlassRevision
12
+ belongs_to :element_klass, class_name: 'Labimotion::ElementKlass'
12
13
 
13
14
  def migrate_workflow
14
15
  return if properties_release.nil? || properties_release['flow'].nil?