labimotion 2.0.0.rc1 → 2.0.0.rc3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ba4a246b95d088b7928826074a223b671bd3ff8ac7c4bce5904ff983aec1534
4
- data.tar.gz: c1393205315928947b688566db60ac311eef1fcfccedbb395e521a2dbdfdfbdd
3
+ metadata.gz: 9d75eb36d68f9212354fef2d83838274d4a4b59a59852c80ce2f0c26f2852c95
4
+ data.tar.gz: 1cc4625e88286bcd2febeb0b2ded75c3091f416c93db7d505e703ed04e8ce849
5
5
  SHA512:
6
- metadata.gz: fbf716f60ca698f40f332b318d55747266d23ffa0c066f2afb5eff44f90c54db1402d8b42e251641fa1564aff167c79abe86411c519653c59ffbca36991a85fd
7
- data.tar.gz: 4dbeae09a3740df12533e217e11d4fbc003894280ccc9d6f46e2042cf4b0ff4b2ce448215a9d918e38b077458caba39e26c55a31870b9e9e7f753f8d25bfc41b
6
+ metadata.gz: c630024f9111ad2c991cf8a442d8958fa4641f1b050a1c9894fab37ad1208537a650065139a13243ba560ad1c77cf77a633a3c74853a7c2857833331b3f03123
7
+ data.tar.gz: 4cee0102f4d4e88ba2e840eccada4294751de262c4b7a232cda167cca23970550df901343a7b1e6a0f1e5c66b4c803bd4e6b0e126ea708ca94a24579e7285b50
@@ -13,8 +13,7 @@ module Labimotion
13
13
  use :create_std_layer_params
14
14
  end
15
15
  post do
16
- # authenticate_admin!('elements')
17
- # create_element_klass(current_user, params)
16
+ authenticate_admin!('standard_layers')
18
17
  create_std_layer(current_user, params)
19
18
  status 201
20
19
  rescue ActiveRecord::RecordInvalid => e
@@ -7,14 +7,13 @@ module Labimotion
7
7
  class StandardLayerAPI < Grape::API
8
8
  include Grape::Kaminari
9
9
  helpers Labimotion::ParamHelpers
10
+ helpers Labimotion::GenericHelpers
10
11
 
11
12
  resource :layers do
12
13
  namespace :get_all_layers do
13
14
  desc 'get all standard layers for designer'
14
15
  get do
15
16
  list = Labimotion::StdLayer.all.sort_by { |e| e.name }
16
- # present list, with: Labimotion::StdLayer, root: 'klass'
17
- # data = Labimotion::StdLayer.represent(col_tree, serializable: true)
18
17
  return { mc: 'ss00', data: list }
19
18
  rescue StandardError => e
20
19
  Labimotion.log_exception(e, current_user)
@@ -24,17 +23,9 @@ module Labimotion
24
23
 
25
24
  namespace :get_standard_layer do
26
25
  desc 'get standard layer by id'
27
- # params do
28
- # requires :id, type: Integer, desc: 'Layer id'
29
- # end
30
26
  route_param :id do
31
- before do
32
- # @element_policy = ElementPolicy.new(current_user, Labimotion::Element.find(params[:id]))
33
- # error!('401 Unauthorized', 401) unless current_user.matrix_check_by_name('genericElement') && @element_policy.read?
34
- # rescue ActiveRecord::RecordNotFound
35
- # error!('404 Not Found', 404)
36
- end
37
27
  get do
28
+ authenticate_admin!('standard_layers')
38
29
  entity = Labimotion::StdLayer.find(params[:id])
39
30
  return { mc: 'ss00', data: entity }
40
31
  rescue StandardError => e
@@ -50,13 +41,9 @@ module Labimotion
50
41
  use :std_layer_save
51
42
  end
52
43
  before do
44
+ authenticate_admin!('standard_layers')
53
45
  cur_layer = Labimotion::StdLayer.find_by(name: params[:key])
54
46
  error!('Error! duplicate name', 409) if cur_layer.present?
55
- # @element_policy = ElementPolicy.new(current_user, Labimotion::Element.find(params[:id]))
56
- # error!('401 Unauthorized', 401) unless current_user.matrix_check_by_name('genericElement') && @element_policy.read?
57
- # rescue ActiveRecord::RecordNotFound
58
- # Labimotion.log_exception(e, current_user)
59
- # error!('404 Not Found', 404)
60
47
  end
61
48
  post do
62
49
  attributes = {
@@ -83,7 +70,7 @@ module Labimotion
83
70
  end
84
71
  route_param :id do
85
72
  before do
86
- # error!('401 Unauthorized', 401) unless ElementPolicy.new(current_user, StdLayer.find(params[:id])).destroy?
73
+ authenticate_admin!('standard_layers')
87
74
  end
88
75
  delete do
89
76
  entity = Labimotion::StdLayer.find(params[:id])
@@ -7,6 +7,7 @@ module Labimotion
7
7
  class VocabularyAPI < Grape::API
8
8
  include Grape::Kaminari
9
9
  helpers Labimotion::ParamHelpers
10
+ helpers Labimotion::GenericHelpers
10
11
 
11
12
  resource :vocab do
12
13
  namespace :save_vocabulary do
@@ -15,7 +16,7 @@ module Labimotion
15
16
  use :vocab_save
16
17
  end
17
18
  before do
18
- # error!('Error! duplicate record', 409) if ???.present?
19
+ authenticate_admin!('vocabularies')
19
20
  rescue ActiveRecord::RecordNotFound
20
21
  error!('404 Not Found', 404)
21
22
  end
@@ -46,17 +47,8 @@ module Labimotion
46
47
  namespace :get_all_vocabularies do
47
48
  desc 'get all standard layers for designer'
48
49
  get do
49
- # merged_data = []
50
- # Dir.glob(Rails.public_path.join('generic', 'vocabularies', '*.json')).each do |file_path|
51
- # file_content = File.read(file_path)
52
- # json_data = JSON.parse(file_content)
53
- # merged_data.concat(json_data)
54
- # end
55
-
56
- # list = Labimotion::Vocabulary.all.sort_by { |e| e.name }
57
- # present list, with: Labimotion::StdLayer, root: 'klass'
50
+ authenticate_admin!('vocabularies')
58
51
  combined_data = Labimotion::VocabularyHandler.load_all_vocabularies
59
- # combined_data = Labimotion::VocabularyEntity.represent(vocabularies, serializable: true)
60
52
  return { mc: 'ss00', data: combined_data }
61
53
  rescue StandardError => e
62
54
  Labimotion.log_exception(e, current_user)
@@ -67,15 +59,9 @@ module Labimotion
67
59
  namespace :field_klasses do
68
60
  desc 'get all field klasses for admin function'
69
61
  get do
70
- # Dir.glob(Rails.public_path.join('generic', 'vocabularies', '*.json')).each do |file_path|
71
- # file_content = File.read(file_path)
72
- # json_data = JSON.parse(file_content)
73
- # merged_data.concat(json_data)
74
- # end
62
+ authenticate_admin!('vocabularies')
75
63
  vocabularies = Labimotion::VocabularyHandler.load_app_vocabularies
76
64
  merged_data = Labimotion::FieldKlassEntity.represent(vocabularies, serializable: true)
77
- # list = Labimotion::Vocabulary.all.sort_by { |e| e.name }
78
- # present list, with: Labimotion::VocabularyEntity, root: 'klass'
79
65
  merged_data
80
66
  rescue StandardError => e
81
67
  Labimotion.log_exception(e, current_user)
@@ -90,7 +76,7 @@ module Labimotion
90
76
  end
91
77
  route_param :id do
92
78
  before do
93
- # error!('401 Unauthorized', 401) unless ElementPolicy.new(current_user, Vocabulary.find(params[:id])).destroy?
79
+ authenticate_admin!('vocabularies')
94
80
  end
95
81
  delete do
96
82
  entity = Labimotion::Vocabulary.find(params[:id])
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labimotion
4
+ module Constants
5
+ module DateTime
6
+ DATE_FORMAT = '%Y-%m-%d'
7
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
8
+ TIME_FORMAT = '%H:%M:%S %Z'
9
+ TIME_ZONE = 'UTC'
10
+ end
11
+
12
+ module File
13
+ ENCODING = 'UTF-8'
14
+ end
15
+
16
+ module Mapper
17
+ NMR_CONFIG = ::File.join(__dir__, 'libs', 'data', 'mapper', 'Source.json').freeze
18
+ end
19
+ end
20
+ end
@@ -12,6 +12,5 @@ module Labimotion
12
12
  def klass_label
13
13
  object&.dataset_klass&.label
14
14
  end
15
-
16
15
  end
17
16
  end
@@ -20,6 +20,7 @@ module Labimotion
20
20
  expose! :thumb_svg
21
21
  expose! :type
22
22
  expose! :uuid
23
+ expose! :user_labels
23
24
  end
24
25
 
25
26
  with_options(anonymize_below: 10) do
@@ -9,7 +9,5 @@ module Labimotion
9
9
  def klass_label
10
10
  object.segment_klass.label
11
11
  end
12
-
13
-
14
12
  end
15
13
  end
@@ -6,16 +6,6 @@ module Labimotion
6
6
  class VocabularyEntity < ApplicationEntity
7
7
  expose :id, :identifier, :name, :label, :field_type, :opid, :term_id,
8
8
  :field_id, :properties, :source, :source_id, :layer_id
9
- # expose :source do |obj|
10
- # (obj[:properties] && obj[:properties]['voc'] && obj[:properties]['voc']['source']) || ''
11
- # end
12
- # expose :source_id do |obj|
13
- # (obj[:properties] && obj[:properties]['voc'] && obj[:properties]['voc']['source_id']) || ''
14
- # end
15
- # expose :layer_id do |obj|
16
- # (obj[:properties] && obj[:properties]['voc'] && obj[:properties]['voc']['layer_id']) || ''
17
- # end
18
-
19
9
  expose :voc do |obj|
20
10
  voc = (obj[:properties] && obj[:properties]['voc']) || {}
21
11
 
@@ -9,7 +9,12 @@ module Labimotion
9
9
  extend Grape::API::Helpers
10
10
 
11
11
  def authenticate_admin!(type)
12
- error!('401 Unauthorized', 401) unless current_user.generic_admin[type]
12
+ unauthorized = -> { error!('401 Unauthorized', 401) }
13
+ if %w[standard_layers vocabularies].include?(type)
14
+ unauthorized.call unless current_user.generic_admin.values_at('elements', 'segments', 'datasets').any?
15
+ else
16
+ unauthorized.call unless current_user.generic_admin[type]
17
+ end
13
18
  end
14
19
 
15
20
  def fetch_klass(name, id)
@@ -134,21 +134,5 @@ module Labimotion
134
134
  optional :select_options, type: Hash, desc: 'selections'
135
135
  optional :option_layers, type: String, desc: 'option'
136
136
  end
137
-
138
- # params :vocabulary_save do
139
- # requires :type, type: String, desc: 'type'
140
- # requires :field, type: String, desc: 'field'
141
- # optional :default, type: String, desc: 'default'
142
- # optional :description, type: String, desc: 'description'
143
- # optional :label, type: String, desc: 'label'
144
- # optional :position, type: Integer, desc: 'position'
145
- # optional :ontology, type: Hash, desc: 'ontology'
146
- # optional :required, type: Boolean, desc: 'is required?'
147
- # optional :sub_fields, type: Array, desc: 'sub_fields'
148
- # optional :text_sub_fields, type: Array, desc: 'text_sub_fields'
149
- # optional :source_type, type: String, desc: 'source type'
150
- # optional :source_id, type: String, desc: 'source id'
151
- # optional :layer_id, type: String, desc: 'layer id'
152
- # end
153
137
  end
154
138
  end
@@ -123,7 +123,6 @@ module Labimotion
123
123
  tmp_file.write(response.parsed_response)
124
124
  tmp_file.rewind
125
125
 
126
- # name = response&.headers && response&.headers['content-disposition']&.split('=')&.last
127
126
  filename = oat.filename
128
127
  name = "#{File.basename(filename, '.*')}.zip"
129
128
  att = Attachment.new(
@@ -0,0 +1,78 @@
1
+ {
2
+ "sourceMap": {
3
+ "sourceSelector": [
4
+ "parm",
5
+ "acqus",
6
+ "procs"
7
+ ],
8
+ "acqus": {
9
+ "file": "acqus",
10
+ "parameters": [
11
+ "DATE",
12
+ "D1",
13
+ "INSTRUM",
14
+ "NS",
15
+ "NUC1",
16
+ "NUC2",
17
+ "PROBHD",
18
+ "PULPROG",
19
+ "SFO1",
20
+ "SFO2",
21
+ "SOLVENT",
22
+ "SW",
23
+ "TD",
24
+ "TE",
25
+ "TITLE"
26
+ ]
27
+ },
28
+ "procs": {
29
+ "file": "pdata/1/procs",
30
+ "parameters": [
31
+ "SI",
32
+ "SF",
33
+ "WDW",
34
+ "LB",
35
+ "GB"
36
+ ]
37
+ },
38
+ "parm": {
39
+ "file": "pdata/1/parm.txt",
40
+ "parameters": [
41
+ "Date_",
42
+ "Time",
43
+ "INSTRUM",
44
+ "PROBHD",
45
+ "SOLVENT",
46
+ "TE",
47
+ "NS",
48
+ "PULPROG",
49
+ "TD",
50
+ "D1",
51
+ "SF",
52
+ "SFO1",
53
+ "SFO2",
54
+ "NUC1",
55
+ "NUC2"
56
+ ]
57
+ },
58
+ "parameters": {
59
+ "DATE": "general.date",
60
+ "D1": "set.done",
61
+ "INSTRUM": "instrument.instrument",
62
+ "NS": "set.ns",
63
+ "NUC1": "set.nucone",
64
+ "NUC2": "set.nuctwo",
65
+ "SF": "set.sf",
66
+ "SFO1": "set.sfoone",
67
+ "SFO2": "set.sfotwo",
68
+ "PROBHD": "equipment.probehead",
69
+ "PULPROG": "set.PULPROG",
70
+ "SOLVENT": "sample_preparation.solvent",
71
+ "TD": "set.td",
72
+ "TE": "set.temperature",
73
+ "TITLE": "software.Name",
74
+ "Version": "software.Version",
75
+ "Time": "general.time"
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'labimotion/utils/utils'
4
+ require 'labimotion/version'
5
+
6
+ module Labimotion
7
+ class DatasetBuilder
8
+ def self.build(container, content)
9
+ return unless valid_input?(container, content)
10
+
11
+ create_dataset_with_metadata(container, content)
12
+ end
13
+
14
+ private
15
+
16
+ def self.valid_input?(container, content)
17
+ container.present? &&
18
+ content.present? &&
19
+ content[:ols].present? &&
20
+ content[:metadata].present?
21
+ end
22
+
23
+ def self.create_dataset_with_metadata(container, content)
24
+ klass = find_dataset_klass(content[:ols])
25
+ return unless klass
26
+
27
+ dataset = create_dataset(container, klass)
28
+ build_result(dataset, content)
29
+ end
30
+
31
+ def self.find_dataset_klass(ols_term_id)
32
+ Labimotion::DatasetKlass.find_by(ols_term_id: ols_term_id)
33
+ end
34
+
35
+ def self.create_dataset(container, klass)
36
+ uuid = SecureRandom.uuid
37
+ props = prepare_properties(klass, uuid)
38
+
39
+ Labimotion::Dataset.create!(
40
+ uuid: uuid,
41
+ dataset_klass_id: klass.id,
42
+ element_type: 'Container',
43
+ element_id: container.id,
44
+ properties: props,
45
+ properties_release: klass.properties_release,
46
+ klass_uuid: klass.uuid
47
+ )
48
+ end
49
+
50
+ def self.prepare_properties(klass, uuid)
51
+ props = klass.properties_release
52
+ props['uuid'] = uuid
53
+ props['pkg'] = Labimotion::Utils.pkg(props['pkg'])
54
+ props['klass'] = 'Dataset'
55
+ props
56
+ end
57
+
58
+ def self.build_result(dataset, content)
59
+ {
60
+ dataset: dataset,
61
+ metadata: content[:metadata],
62
+ ols: content[:ols],
63
+ parameters: content[:parameters]
64
+ }
65
+ end
66
+
67
+ private_class_method :valid_input?, :create_dataset_with_metadata, :find_dataset_klass, :create_dataset,
68
+ :prepare_properties, :build_result
69
+ end
70
+ end
@@ -1,301 +1,266 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'labimotion/libs/dataset_builder'
3
4
  require 'labimotion/version'
5
+ require 'labimotion/utils/mapper_utils'
4
6
  require 'labimotion/utils/utils'
5
7
 
6
8
  module Labimotion
7
9
  ## NmrMapper
8
10
  class NmrMapper
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
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'
27
27
  end
28
28
  end
29
29
 
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
30
+ class << self
31
+ def process_ds(id, current_user = {})
32
+ att = find_attachment(id)
33
+ return Labimotion::ConState::NONE if att.nil?
48
34
 
49
- def self.process(att, id, content)
50
- return if att.nil? || content.nil?
35
+ result = process(att)
36
+ return Labimotion::ConState::NONE if result.nil?
51
37
 
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
38
+ handle_process_result(result, att, id, current_user)
57
39
  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
67
40
 
68
- def self.fetch_content(id)
69
- atts = Attachment.where(attachable_id: id)
70
- return if atts.nil?
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?
71
48
 
72
- atts.each do |att|
73
- content = Labimotion::NmrMapper.ts('read', att.id)
74
- return content if content.present?
49
+ extracted_data[:parameters] = config['sourceMap']['parameters']
50
+ extracted_data
75
51
  end
76
- end
77
52
 
53
+ def generate_ds(_id, cid, data, current_user = {}, element = nil)
54
+ return if data.nil? || cid.nil?
78
55
 
79
- def self.generate_ds(id, cid, data, current_user = {})
80
- return if data.nil? || cid.nil?
56
+ obj = Labimotion::NmrMapper.build_ds(cid, data[:content])
57
+ return if obj.nil? || obj[:ols].nil?
81
58
 
82
- obj = Labimotion::NmrMapper.build_ds(cid, data[:content])
83
- return if obj.nil? || obj[:ols].nil?
59
+ Labimotion::NmrMapper.update_ds(cid, obj, current_user, element)
60
+ end
84
61
 
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
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
88
67
 
89
- def self.update_ds_13c(id, obj)
90
- # dataset = obj[:dataset]
91
- # metadata = obj[:metadata]
92
- # new_prop = dataset.properties
68
+ def build_ds(id, content)
69
+ ds = find_container(id)
70
+ return if ds.nil? || content.nil?
93
71
 
94
- # dataset.properties = new_prop
95
- # dataset.save!
96
- end
72
+ Labimotion::DatasetBuilder.build(ds, content)
73
+ end
97
74
 
98
- def self.set_data(prop, field, idx, layer_name, field_name, value)
99
- return if field['field'] != field_name || value&.empty?
75
+ private
100
76
 
101
- field['value'] = value
102
- prop[Labimotion::Prop::LAYERS][layer_name][Labimotion::Prop::FIELDS][idx] = field
103
- prop
104
- end
77
+ def finalize_ds(new_prop)
78
+ Constants::FG_FINALIZE.each do |field_path|
79
+ field = find_field(new_prop, field_path)
80
+ next unless field
105
81
 
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
82
+ update_finalized_field(field)
118
83
  end
84
+ new_prop
85
+ end
119
86
 
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
126
- end
87
+ def sys_to_ds(new_prop, element, current_user)
88
+ Constants::FG_SYSTEM.each do |field_path|
89
+ field = find_field(new_prop, field_path)
90
+ next unless field
127
91
 
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
92
+ update_system_field(field, current_user, element)
134
93
  end
94
+ new_prop
95
+ end
96
+
97
+ def params_to_ds(obj, new_prop)
98
+ metadata = obj[:metadata]
99
+ parameters = obj[:parameters]
100
+
101
+ parameters.each do |param_key, field_path|
102
+ next if skip_parameter?(metadata, param_key)
135
103
 
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
104
+ update_param_field(new_prop, field_path, param_key, metadata)
140
105
  end
106
+ new_prop
141
107
  end
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
148
- end
149
- if fi['field'] == 'id'
150
- fi['value'] = element.id
151
- new_prop[Labimotion::Prop::LAYERS]['sample_details'][Labimotion::Prop::FIELDS][idx] = fi
152
- 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) }
153
116
  end
154
117
 
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
162
- end
118
+ def find_attachment(id)
119
+ Attachment.find_by(id: id, con_state: Labimotion::ConState::NMR)
163
120
  end
164
121
 
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
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)
172
129
  end
173
130
  end
174
131
 
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
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
184
136
  end
185
137
 
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
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
229
180
  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
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 find_field(properties, field_path)
189
+ layer_name, field_name = field_path.split('.')
190
+ fields = properties.dig(Labimotion::Prop::LAYERS, layer_name, Labimotion::Prop::FIELDS)
191
+ return unless fields
192
+
193
+ fields.find { |f| f['field'] == field_name }
194
+ end
195
+
196
+ def update_param_field(properties, field_path, param_key, metadata)
197
+ field = find_field(properties, field_path)
198
+ return unless field
199
+
200
+ update_field_value(field, param_key, metadata)
201
+ update_field_extend(field, param_key, metadata)
202
+ end
203
+
204
+ def update_duplicate_field(field_name, metadata)
205
+ case field_name
206
+ when 'time' then metadata['DATE']
207
+ when 'Version' then metadata['TITLE']
236
208
  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
209
+ end
210
+
211
+ def update_field_value(field, param_key, metadata)
212
+ field['value'] = format_field_value(field, param_key, metadata)
213
+ rescue StandardError => e
214
+ Rails.logger.error "Error converting value for #{param_key}: #{e.message}"
215
+ field['value'] = ''
216
+ end
217
+
218
+ def format_field_value(field, param_key, metadata)
219
+ if field['type'] == 'integer'
220
+ Integer(metadata[param_key.to_s])
221
+ elsif Constants::DUP_FIELDS.include?(param_key.to_s.downcase)
222
+ update_duplicate_field(field['field'], metadata)
223
+ else
224
+ metadata[param_key.to_s]
243
225
  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
226
+ end
227
+
228
+ def update_finalized_field(field)
229
+ case field['field']
230
+ when 'temperature'
231
+ field['value_system'] = 'K'
232
+ when 'date', 'time'
233
+ field['value'] = Labimotion::MapperUtils.format_timestamp(field['value'], field['field'])
234
+ when 'Name'
235
+ field['value'] = 'TopSpin' if field['value'].to_s.include?('TopSpin')
236
+ when 'Version'
237
+ field['value'] = field['value'].to_s.split('TopSpin').last.strip if field['value'].to_s.include?('TopSpin')
250
238
  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
239
+ end
240
+
241
+ def update_system_field(field, current_user, element)
242
+ field['value'] = determine_field_value(field['field'], current_user, element)
243
+ end
244
+
245
+ def determine_field_value(field_name, current_user, element)
246
+ case field_name
247
+ when 'creator'
248
+ current_user&.name if current_user.present?
249
+ when 'label', 'id'
250
+ get_sample_value(field_name, element)
257
251
  end
258
252
  end
259
- new_prop = Labimotion::VocabularyHandler.update_vocabularies(new_prop, current_user, element)
260
- dataset.properties = new_prop
261
- dataset.save!
262
- end
263
253
 
264
- def self.ts(method, identifier, params = nil)
265
- Rails.cache.send(method, "#{Labimotion::NmrMapper.new.class.name}#{identifier}", params)
266
- end
254
+ def get_sample_value(field_name, element)
255
+ return unless element.present? && element.is_a?(Sample)
267
256
 
268
- def self.clean(id)
269
- Labimotion::NmrMapper.ts('delete', id)
270
- end
257
+ field_name == 'label' ? element.short_label : element.id
258
+ end
271
259
 
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 }
260
+ def update_field_extend(field, param_key, metadata)
261
+ field['device'] = metadata[param_key.to_s]
262
+ field['dkey'] = param_key.to_s
263
+ end
299
264
  end
300
265
  end
301
266
  end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'time'
5
+ require 'zip'
6
+ require 'labimotion/constants'
7
+
8
+ module Labimotion
9
+ class MapperUtils
10
+ class << self
11
+ def load_config(config_json)
12
+ JSON.parse(config_json)
13
+ rescue JSON::ParserError => e
14
+ Rails.logger.error "Error parsing JSON: #{e.message}"
15
+ nil
16
+ rescue Errno::ENOENT => e
17
+ Rails.logger.error "Config file not found at #{Constants::Mapper::NMR_CONFIG}: #{e.message}"
18
+ nil
19
+ rescue StandardError => e
20
+ Rails.logger.error "Unexpected error loading config: #{e.message}"
21
+ nil
22
+ end
23
+
24
+ def load_brucker_config
25
+ config = load_config(File.read(Constants::Mapper::NMR_CONFIG))
26
+ return if config.nil? || config['sourceMap'].nil?
27
+
28
+ source_selector = config['sourceMap']['sourceSelector']
29
+ return if source_selector.blank?
30
+
31
+ parameters = config['sourceMap']['parameters']
32
+ return if parameters.blank?
33
+
34
+ config
35
+ end
36
+
37
+ def extract_data_from_zip(zip_file_url, source_map)
38
+ return nil if zip_file_url.nil?
39
+
40
+ process_zip_file(zip_file_url, source_map)
41
+ rescue Zip::Error => e
42
+ Rails.logger.error "Zip file error: #{e.message}"
43
+ nil
44
+ rescue StandardError => e
45
+ Rails.logger.error "Unexpected error extracting metadata: #{e.message}"
46
+ nil
47
+ end
48
+
49
+ def extract_parameters(file_content, parameter_names)
50
+ return nil if file_content.blank? || parameter_names.blank?
51
+
52
+ patterns = {
53
+ standard: build_parameter_pattern(parameter_names, :standard),
54
+ parm: build_parameter_pattern(parameter_names, :parm)
55
+ }
56
+
57
+ extracted_parameters = {}
58
+ begin
59
+ file_content.each_line do |line|
60
+ if (match = match_parameter(line, patterns))
61
+ value = clean_value(match[:value])
62
+ extracted_parameters[match[:param_name]] = value
63
+ end
64
+ end
65
+ rescue StandardError => e
66
+ Rails.logger.error "Error reading file content: #{e.message}"
67
+ return nil
68
+ end
69
+ extracted_parameters.compact_blank!
70
+ extracted_parameters
71
+ end
72
+
73
+ def format_timestamp(timestamp_str, give_format = nil)
74
+ return nil if timestamp_str.blank?
75
+
76
+ begin
77
+ timestamp = Integer(timestamp_str)
78
+ time_object = Time.at(timestamp).in_time_zone(Constants::DateTime::TIME_ZONE)
79
+ case give_format
80
+ when 'date'
81
+ time_object.strftime(Constants::DateTime::DATE_FORMAT)
82
+ when 'time'
83
+ time_object.strftime(Constants::DateTime::TIME_FORMAT)
84
+ else
85
+ time_object.strftime(Constants::DateTime::DATETIME_FORMAT)
86
+ end
87
+ rescue ArgumentError, TypeError => e
88
+ Rails.logger.error "Error parsing timestamp '#{timestamp_str}': #{e.message}"
89
+ nil
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def build_parameter_pattern(parameter_names, format)
96
+ pattern = case format
97
+ when :standard
98
+ '^\\s*##?\\s*[$]?(?<param_name>%s)\\s*(?:=\\s*)?(?<value>.*?)\\s*$'
99
+ when :parm
100
+ '^\\s*(?<param_name>%s)\\s+(?<value>[^\\s].*?)(?:\\s+[A-Za-z]+)?\\s*$'
101
+ end
102
+
103
+ param_regex = parameter_names.map { |p| "\\b#{Regexp.escape(p)}\\b" }.join('|')
104
+ Regexp.new(pattern % param_regex)
105
+ end
106
+
107
+ def match_parameter(line, patterns)
108
+ patterns.each_value do |pattern|
109
+ match = line.match(pattern)
110
+ return match if match
111
+ end
112
+ nil
113
+ end
114
+
115
+ def clean_value(value)
116
+ value = value.strip
117
+ value = value[1..-2].strip if value.start_with?('<') && value.end_with?('>')
118
+ value
119
+ end
120
+
121
+ def process_zip_file(zip_file_url, source_map)
122
+ final_parameters = {}
123
+
124
+ Zip::File.open(zip_file_url) do |zip_file|
125
+ source_map['sourceSelector'].each do |source_name|
126
+ process_source(zip_file, source_map[source_name], final_parameters)
127
+ end
128
+ end
129
+
130
+ return { is_bagit: false, metadata: final_parameters } if final_parameters.present?
131
+
132
+ nil
133
+ end
134
+
135
+ def process_source(zip_file, source_config, final_parameters)
136
+ return if invalid_source_config?(source_config)
137
+
138
+ zip_file.each do |entry|
139
+ if source_file?(entry, source_config)
140
+ process_file_entry(entry, source_config['parameters'], final_parameters)
141
+ elsif bagit_metadata_file?(entry)
142
+ return { is_bagit: true, metadata: nil }
143
+ end
144
+ end
145
+ end
146
+
147
+ def process_file_entry(entry, parameters, final_parameters)
148
+ file_content = entry.get_input_stream.read.force_encoding(Constants::File::ENCODING)
149
+ extracted_parameters = extract_parameters(file_content, parameters)
150
+ final_parameters.merge!(extracted_parameters) if extracted_parameters.present?
151
+ end
152
+
153
+ def invalid_source_config?(source_config)
154
+ source_config.nil? ||
155
+ source_config['file'].nil? ||
156
+ source_config['parameters'].nil?
157
+ end
158
+
159
+ def source_file?(entry, source_config)
160
+ entry.name.include?(source_config['file'])
161
+ end
162
+
163
+ def bagit_metadata_file?(entry)
164
+ entry.name.include?('metadata/') &&
165
+ entry.name.include?('converter.json')
166
+ end
167
+ end
168
+ end
169
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  ## Labimotion Version
4
4
  module Labimotion
5
- VERSION = '2.0.0.rc1'
5
+ VERSION = '2.0.0.rc3'
6
6
  end
data/lib/labimotion.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # In your_gem_name.rb or main Ruby file
2
2
  module Labimotion
3
-
4
3
  autoload :CONF, 'labimotion/conf'
5
4
  autoload :VERSION, 'labimotion/version'
5
+ autoload :Constants, 'labimotion/constants'
6
6
 
7
7
  def self.logger
8
8
  @@labimotion_logger ||= Logger.new(Rails.root.join('log/labimotion.log')) # rubocop:disable Style/ClassVars
@@ -13,6 +13,7 @@ module Labimotion
13
13
  Labimotion.logger.error(exception.backtrace.join("\n"))
14
14
  end
15
15
 
16
+ autoload :MapperUtils, 'labimotion/utils/mapper_utils'
16
17
  autoload :Utils, 'labimotion/utils/utils'
17
18
 
18
19
  ######## APIs
@@ -62,6 +63,7 @@ module Labimotion
62
63
 
63
64
  ######## Libs
64
65
  autoload :Converter, 'labimotion/libs/converter'
66
+ autoload :DatasetBuilder, 'labimotion/libs/dataset_builder'
65
67
  autoload :NmrMapper, 'labimotion/libs/nmr_mapper'
66
68
  autoload :NmrMapperRepo, 'labimotion/libs/nmr_mapper_repo' ## for Chemotion Repository
67
69
  autoload :TemplateHub, 'labimotion/libs/template_hub'
@@ -114,6 +116,4 @@ module Labimotion
114
116
  autoload :Datasetable, 'labimotion/models/concerns/datasetable'
115
117
  autoload :AttachmentConverter, 'labimotion/models/concerns/attachment_converter.rb'
116
118
  autoload :LinkedProperties, 'labimotion/models/concerns/linked_properties'
117
-
118
-
119
119
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: labimotion
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chia-Lin Lin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-12-06 00:00:00.000000000 Z
12
+ date: 2025-02-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -47,6 +47,7 @@ files:
47
47
  - lib/labimotion/collection/export.rb
48
48
  - lib/labimotion/collection/import.rb
49
49
  - lib/labimotion/conf.rb
50
+ - lib/labimotion/constants.rb
50
51
  - lib/labimotion/entities/application_entity.rb
51
52
  - lib/labimotion/entities/dataset_entity.rb
52
53
  - lib/labimotion/entities/dataset_klass_entity.rb
@@ -75,8 +76,10 @@ files:
75
76
  - lib/labimotion/helpers/vocabulary_helpers.rb
76
77
  - lib/labimotion/libs/attachment_handler.rb
77
78
  - lib/labimotion/libs/converter.rb
79
+ - lib/labimotion/libs/data/mapper/Source.json
78
80
  - lib/labimotion/libs/data/vocab/Standard.json
79
81
  - lib/labimotion/libs/data/vocab/System.json
82
+ - lib/labimotion/libs/dataset_builder.rb
80
83
  - lib/labimotion/libs/export_dataset.rb
81
84
  - lib/labimotion/libs/export_element.rb
82
85
  - lib/labimotion/libs/nmr_mapper.rb
@@ -114,6 +117,7 @@ files:
114
117
  - lib/labimotion/utils/export_utils.rb
115
118
  - lib/labimotion/utils/field_type.rb
116
119
  - lib/labimotion/utils/import_utils.rb
120
+ - lib/labimotion/utils/mapper_utils.rb
117
121
  - lib/labimotion/utils/prop.rb
118
122
  - lib/labimotion/utils/search.rb
119
123
  - lib/labimotion/utils/serializer.rb