libis-metadata 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +39 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/exe/metadata +5 -0
  12. data/lib/libis/metadata/cli/cli_downloader.rb +182 -0
  13. data/lib/libis/metadata/cli/cli_helper.rb +74 -0
  14. data/lib/libis/metadata/command_line.rb +25 -0
  15. data/lib/libis/metadata/downloader.rb +117 -0
  16. data/lib/libis/metadata/dublin_core_record.rb +115 -0
  17. data/lib/libis/metadata/field_format.rb +119 -0
  18. data/lib/libis/metadata/fix_field.rb +33 -0
  19. data/lib/libis/metadata/mapper.rb +80 -0
  20. data/lib/libis/metadata/mappers/flandrica.rb +76 -0
  21. data/lib/libis/metadata/mappers/kuleuven.rb +1929 -0
  22. data/lib/libis/metadata/mappers/scope.rb +46 -0
  23. data/lib/libis/metadata/marc21_record.rb +49 -0
  24. data/lib/libis/metadata/marc_record.rb +285 -0
  25. data/lib/libis/metadata/parser/basic_parser.rb +116 -0
  26. data/lib/libis/metadata/parser/dublin_core_parser.rb +35 -0
  27. data/lib/libis/metadata/parser/marc21_parser.rb +205 -0
  28. data/lib/libis/metadata/parser/marc_format_parser.rb +51 -0
  29. data/lib/libis/metadata/parser/marc_rules.rb +34 -0
  30. data/lib/libis/metadata/parser/marc_select_parser.rb +24 -0
  31. data/lib/libis/metadata/parser/patch.rb +22 -0
  32. data/lib/libis/metadata/parser/subfield_criteria_parser.rb +70 -0
  33. data/lib/libis/metadata/parsers.rb +12 -0
  34. data/lib/libis/metadata/sharepoint_mapping.rb +119 -0
  35. data/lib/libis/metadata/sharepoint_record.rb +262 -0
  36. data/lib/libis/metadata/var_field.rb +242 -0
  37. data/lib/libis/metadata/version.rb +5 -0
  38. data/lib/libis/metadata.rb +25 -0
  39. data/lib/libis-metadata.rb +1 -0
  40. data/metadata.gemspec +39 -0
  41. metadata +266 -0
@@ -0,0 +1,35 @@
1
+ require 'parslet'
2
+
3
+ require_relative 'basic_parser'
4
+
5
+ module Libis
6
+ module Metadata
7
+ module Parser
8
+ # noinspection RubyResolve
9
+
10
+ # New style parsers and converters for metadata. New, not finished and untested.
11
+ class DublinCoreParser < Libis::Metadata::Parser::BasicParser
12
+ rule(:namespace) {match('[^:]').repeat(1).as(:namespace) >> str(':')}
13
+ rule(:namespace?) {namespace.maybe}
14
+
15
+ rule(:attribute) {namespace? >> name_string.as(:name) >> str('=') >> str('"') >> match('[^"]').repeat(1).as(:value) >> str('"')}
16
+ rule(:attributes) {attribute >> (spaces >> attribute).repeat}
17
+ rule(:attributes?) {attributes.maybe}
18
+ rule(:element) {name_string.as(:element)}
19
+ rule(:DC) {namespace >> element >> (spaces >> attributes.as(:attributes)).maybe}
20
+
21
+ root(:DC)
22
+
23
+ def to_target(tree)
24
+ tree = tree[:DC]
25
+ return nil unless tree
26
+ result = "xml['#{tree[:namespace]}'].#{tree[:element]}("
27
+ tree[:attributes].each {|attribute| result += "'#{attribute[:name]}' => '#{attribute[:value]}'"}
28
+ result + ').text'
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,205 @@
1
+ require 'parslet'
2
+
3
+ require_relative 'basic_parser'
4
+ require_relative 'marc_rules'
5
+
6
+ module Libis
7
+ module Metadata
8
+ module Parser
9
+ # noinspection RubyResolve
10
+
11
+ # New style parsers and converters for metadata. New, not finished and untested.
12
+ class Marc21Parser < Libis::Metadata::Parser::BasicParser
13
+
14
+ root(:marc21)
15
+ rule(:marc21) {select.as(:select) | format.as(:format)}
16
+
17
+ # select syntax
18
+ rule(:select) do
19
+ str('MARC') >>
20
+ spaces? >> tag.as(:tag) >>
21
+ spaces? >> indicator.maybe.as(:ind1) >> indicator.maybe.as(:ind2) >>
22
+ spaces? >> subfield.maybe.as(:subfield) >>
23
+ spaces? >> condition.maybe.as(:condition)
24
+ end
25
+ rule(:condition) {grouped_anonymous(cond_format.as(:cond_format))}
26
+ rule(:cond_format) {cond_entry.repeat(1).maybe.as(:entry) >> postfix.maybe.as(:postfix)}
27
+ rule(:cond_entry) {sf_reference | method_call | cond_group}
28
+ rule(:cond_group) {(prefix.maybe.as(:prefix) >> grouped(cond_format)).as(:cond_group)}
29
+
30
+ # Formatting syntax
31
+ rule(:format) {entry.repeat(1).maybe.as(:entry) >> postfix.maybe.as(:postfix)}
32
+
33
+ rule(:entry) {sf_reference | method_call | group}
34
+ # noinspection RubyArgCount
35
+ rule(:group) {(prefix.maybe.as(:prefix) >> grouped(format)).as(:group)}
36
+ # noinspection RubyArgCount
37
+ rule(:method_call) {(prefix.maybe.as(:prefix) >> sf_indicator >> grouped_anonymous(format, lrparen)).as(:method_call)}
38
+
39
+ # pre- and postfix
40
+ rule(:prefix) {other.repeat(1)}
41
+ rule(:prefix) {text}
42
+ rule(:postfix) {other.repeat(1)}
43
+ rule(:postfix) {text}
44
+
45
+ # subfield reference
46
+ rule(:sf_reference) {sf_variable.as(:subfield) | sf_fixed.as(:fixfield)}
47
+
48
+ rule(:sf_variable) {prefix.maybe.as(:prefix) >> sf_indicator >> sf_repeat.maybe.as(:repeat) >> sf_name}
49
+ rule(:sf_repeat) {star >> any_quoted(:separator).maybe}
50
+
51
+ rule(:sf_fixed) {prefix.maybe.as(:prefix) >> sf_indicator >> lsparen >> (sf_range | sf_position | sf_star) >> rsparen}
52
+ rule(:sf_star) {star.as(:all)}
53
+ rule(:sf_position) {integer.as(:position)}
54
+ rule(:sf_range) {integer.as(:first) >> minus >> integer.as(:last)}
55
+
56
+ rule(:other) {paren.absent? >> dollar.absent? >> any | litteral_dollar}
57
+
58
+ # tag
59
+ rule(:tag) {tag_numeric | tag_alpha}
60
+ rule(:tag_numeric) {number.repeat(3, 3)}
61
+ rule(:tag_alpha) {character.repeat(3, 3)}
62
+
63
+ # indicator
64
+ rule(:indicator) {hashtag | underscore | number | character}
65
+
66
+ # subfield
67
+ rule(:sf_indicator) {dollar}
68
+ rule(:sf_name) {(character | number).as(:name)}
69
+ rule(:sf_names) {(character | number).repeat(1).as(:names)}
70
+ rule(:subfield) {sf_indicator >> sf_name}
71
+ rule(:litteral_dollar) {dollar >> dollar}
72
+
73
+ # noinspection RubyResolve
74
+ class Transformer < Parslet::Transform
75
+ rule(name: simple(:name)) {"#{name}"}
76
+ # select transformation rules
77
+ rule(cond_group: {
78
+ prefix: simple(:prefix),
79
+ lparen: simple(:lparen),
80
+ entry: simple(:entry),
81
+ postfix: simple(:postfix),
82
+ rparen: simple(:rparen)}) {
83
+ "#{prefix}#{lparen}#{entry}#{postfix}#{rparen}"
84
+ }
85
+ rule(cond_group: {
86
+ prefix: simple(:prefix),
87
+ lparen: simple(:lparen),
88
+ entry: sequence(:entry),
89
+ postfix: simple(:postfix),
90
+ rparen: simple(:rparen)}) {
91
+ "#{prefix}#{lparen}#{entry.join}#{postfix}#{rparen}"
92
+ }
93
+ rule(cond_format: {
94
+ entry: sequence(:entry),
95
+ postfix: simple(:postfix)
96
+ }) {", Proc.new { |f| #{entry.join}#{postfix} }"}
97
+ rule(select: {
98
+ tag: simple(:tag),
99
+ ind1: simple(:ind1),
100
+ ind2: simple(:ind2),
101
+ subfield: simple(:subfield),
102
+ condition: simple(:condition)
103
+ }) {"record.select_fields('#{tag}#{ind1 || '#'}#{ind2 || '#'}#{subfield}'#{condition || ''})"}
104
+ # format transformation rules
105
+ rule(format: {
106
+ entry: sequence(:entries),
107
+ postfix: simple(:postfix)
108
+ }) do
109
+ if entries.size == 1 && postfix.nil?
110
+ entries.first
111
+ else
112
+ "field_format(#{entries.join(',')}#{", postfix: '#{postfix}'" if postfix}).to_s"
113
+ end
114
+ end
115
+ rule(group: {
116
+ prefix: simple(:prefix),
117
+ lparen: simple(:lparen),
118
+ entry: nil,
119
+ postfix: simple(:postfix),
120
+ rparen: simple(:rparen)}) {
121
+ "#{prefix}#{lparen}#{postfix}#{rparen}"
122
+ }
123
+ rule(group: {
124
+ prefix: simple(:prefix),
125
+ lparen: simple(:lparen),
126
+ entry: '',
127
+ postfix: simple(:postfix),
128
+ rparen: simple(:rparen)}) {
129
+ "#{prefix}#{lparen}#{postfix}#{rparen}"
130
+ }
131
+ rule(group: {
132
+ prefix: simple(:prefix),
133
+ lparen: simple(:lparen),
134
+ entry: simple(:entry),
135
+ postfix: simple(:postfix),
136
+ rparen: simple(:rparen)}) {
137
+ "field_format(#{entry}#{", prefix: '#{prefix}#{lparen}'" if prefix || lparen}#{", postfix: '#{postfix}#{rparen}'" if postfix || rparen}).to_s"
138
+ }
139
+ rule(group: {
140
+ prefix: simple(:prefix),
141
+ lparen: simple(:lparen),
142
+ entry: sequence(:entries),
143
+ postfix: simple(:postfix),
144
+ rparen: simple(:rparen)}) {
145
+ "field_format(#{entries.join(',')}#{", prefix: '#{prefix}#{lparen}'" if prefix || lparen}#{", postfix: '#{postfix}#{rparen}'" if postfix || rparen}).to_s"
146
+ }
147
+ rule(fixfield: {
148
+ prefix: nil,
149
+ all: '*'
150
+ }) {'f[]'}
151
+ rule(fixfield: {
152
+ prefix: simple(:prefix),
153
+ all: '*'
154
+ }) {"field_format(f[], prefix: '#{prefix}').to_s"}
155
+ rule(fixfield: {
156
+ prefix: nil,
157
+ position: simple(:position)
158
+ }) {"f[#{position}]"}
159
+ rule(fixfield: {
160
+ prefix: simple(:prefix),
161
+ position: simple(:position)
162
+ }) do
163
+ if prefix
164
+ "field_format(f[#{position}], prefix: '#{prefix}').to_s"
165
+ else
166
+ "f[#{position}]"
167
+ end
168
+ end
169
+ rule(fixfield: {
170
+ prefix: nil,
171
+ first: simple(:from),
172
+ last: simple(:to)
173
+ }) {"f[#{from},#{to}]"}
174
+ rule(fixfield: {
175
+ prefix: simple(:prefix),
176
+ first: simple(:from),
177
+ last: simple(:to)
178
+ }) {"field_format(f[#{from},#{to}], prefix: '#{prefix}').to_s"}
179
+ rule(subfield: {
180
+ prefix: simple(:prefix),
181
+ repeat: nil,
182
+ name: simple(:name),
183
+ }) {"field_format(f.subfield('#{name}'), prefix: '#{prefix}').to_s"}
184
+ rule(subfield: {
185
+ prefix: simple(:prefix),
186
+ repeat: {separator: simple(:separator)},
187
+ name: simple(:name),
188
+ }) {"field_format(f.subfield_array('#{name}')#{", prefix: '#{prefix}'" if prefix}, join: '#{separator}').to_s"}
189
+ rule(subfield: {
190
+ prefix: simple(:prefix),
191
+ repeat: '*',
192
+ name: simple(:name),
193
+ }) {"field_format(f.subfield_array('#{name}')#{", prefix: '#{prefix}'" if prefix}, join: ';').to_s"}
194
+ rule(subfield: {
195
+ prefix: nil,
196
+ repeat: nil,
197
+ name: simple(:name),
198
+ }) {"f.subfield('#{name}')"}
199
+ end
200
+
201
+ end
202
+
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,51 @@
1
+ require 'parslet'
2
+
3
+ require_relative 'basic_parser'
4
+ require_relative 'marc_rules'
5
+
6
+ module Libis
7
+ module Metadata
8
+ module Parser
9
+ # noinspection RubyResolve
10
+
11
+ # New style parsers and converters for metadata. New, not finished and untested.
12
+ class MarcFormatParser < Libis::Metadata::Parser::BasicParser
13
+ include Libis::Metadata::Parser::MarcRules
14
+
15
+ root(:mapping)
16
+
17
+ rule(:mapping) {entry.repeat(1).as(:entry) >> postfix?.as(:postfix)}
18
+
19
+ rule(:entry) {group.as(:group) | sf_reference}
20
+ rule(:group) {prefix?.as(:prefix) >> grouped(mapping)}
21
+
22
+ # pre- and postfix
23
+ rule(:prefix) {other.repeat(1)}
24
+ rule(:prefix) {text}
25
+ rule(:prefix?) {prefix.maybe}
26
+ rule(:postfix) {other.repeat(1)}
27
+ rule(:postfix) {text}
28
+ rule(:postfix?) {postfix.maybe}
29
+
30
+ # subfield reference
31
+ rule(:sf_reference) {sf_variable.as(:subfield) | sf_fixed.as(:fixfield)}
32
+
33
+ rule(:sf_variable) {prefix?.as(:prefix) >> sf_indicator >> sf_repeat?.as(:repeat) >> sf_name}
34
+ rule(:sf_repeat) {star >>
35
+ (dquote >> not_dquote.repeat.as(:separator) >> dquote |
36
+ squote >> not_squote.repeat.as(:separator) >> squote
37
+ ).maybe
38
+ }
39
+ rule(:sf_repeat?) {sf_repeat.maybe}
40
+
41
+ rule(:sf_fixed) {prefix?.as(:prefix) >> sf_indicator >> str('@') >> (sf_position | sf_range | sf_star)}
42
+ rule(:sf_position) {lsparen >> integer.as(:position) >> rsparen}
43
+ rule(:sf_range) {lsparen >> integer.as(:first) >> minus >> integer.as(:last) >> rsparen}
44
+ rule(:sf_star) {star.as(:all)}
45
+
46
+ rule(:other) {paren.absent? >> dollar.absent? >> any | str('$$')}
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,34 @@
1
+ require 'parslet'
2
+
3
+ module Libis
4
+ module Metadata
5
+ module Parser
6
+ # noinspection RubyResolve
7
+
8
+ # New style parsers and converters for metadata. New, not finished and untested.
9
+ module MarcRules
10
+ include Parslet
11
+
12
+ # tag
13
+ rule(:tag) {tag_numeric | tag_alpha}
14
+ rule(:tag_numeric) {number.repeat(3, 3)}
15
+ rule(:tag_alpha) {character.repeat(3, 3)}
16
+
17
+ # indicator
18
+ rule(:indicator) {hashtag | underscore | number | character}
19
+ rule(:indicator?) {indicator.maybe}
20
+ rule(:indicators) {indicator?.as(:ind1) >> indicator?.as(:ind2)}
21
+
22
+ # subfield
23
+ rule(:sf_indicator) {dollar}
24
+ rule(:sf_name) {(character | number).as(:name)}
25
+ rule(:sf_name?) {sf_name.maybe}
26
+ rule(:sf_names) {(character | number).repeat(1).as(:names)}
27
+ rule(:sf_names?) {sf_names.maybe}
28
+ rule(:subfield) {sf_indicator >> sf_name}
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ require 'parslet'
2
+
3
+ require_relative 'basic_parser'
4
+ require_relative 'marc_rules'
5
+
6
+ module Libis
7
+ module Metadata
8
+ module Parser
9
+ # noinspection RubyResolve
10
+
11
+ # New style parsers and converters for metadata. New, not finished and untested.
12
+ class MarcSelectParser < Libis::Metadata::Parser::BasicParser
13
+ include Libis::Metadata::MarcRules
14
+ root(:MARC)
15
+ rule(:MARC) {str('MARC') >> spaces? >> tag.as(:tag) >> spaces? >> indicators >> spaces? >> subfield.maybe.as(:subfield)}
16
+
17
+ # subfield
18
+ # rule(:sf_condition) { sf_indicator >> sf_names >> (space >> sf_names).repeat }
19
+ # rule(:sf_names) { sf_name.repeat(1) }
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # New style parsers and converters for metadata. New, not finished and untested.
2
+ class Parslet::Pattern
3
+
4
+ def element_match_hash(tree, exp, bindings)
5
+ return false if exp.size < tree.size
6
+ exp.each do |expected_key, expected_value|
7
+ if expected_key.to_s =~ /^(.*)\?$/
8
+ expected_key = expected_key.is_a?(Symbol) ? $1.to_sym : $1
9
+ return true unless tree.has_key? expected_key
10
+ end
11
+
12
+ return false unless tree.has_key? expected_key
13
+
14
+ # Recurse into the value and stop early on failure
15
+ value = tree[expected_key]
16
+ return false unless element_match(value, expected_value, bindings)
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ end
@@ -0,0 +1,70 @@
1
+ require 'parslet'
2
+
3
+ require_relative 'basic_parser'
4
+
5
+ module Libis
6
+ module Metadata
7
+ module Parser
8
+ # noinspection RubyResolve
9
+
10
+ # New style parsers and converters for metadata. New, not finished and untested.
11
+ class SubfieldCriteriaParser < Libis::Metadata::Parser::BasicParser
12
+
13
+ root(:criteria)
14
+
15
+ rule(:criteria) {selection >> (spaces >> selection).repeat}
16
+
17
+ rule(:selection) {must >> must_not.maybe}
18
+
19
+ rule(:must) {names.as(:must).maybe >> (one_of | only_one_of).maybe}
20
+ rule(:must_not) {minus >> must.as(:not)}
21
+
22
+ rule(:one_of) {lrparen >> names.as(:one_of) >> rrparen}
23
+ rule(:only_one_of) {lcparen >> names.as(:only_one_of) >> rcparen}
24
+
25
+ rule(:names) {(character | number).repeat(1)}
26
+
27
+ def criteria_to_s(criteria)
28
+ case criteria
29
+ when Array
30
+ # leave as is
31
+ when Hash
32
+ criteria = [criteria]
33
+ else
34
+ return criteria
35
+ end
36
+ criteria.map {|selection| selection_to_s(selection)}.join(' ')
37
+ end
38
+
39
+ def selection_to_s(selection)
40
+ return selection unless selection.is_a? Hash
41
+ result = "#{selection[:must]}"
42
+ result += "(#{selection[:one_of]})" if selection[:one_of]
43
+ result += "{#{selection[:only_one_of]}}" if selection[:only_one_of]
44
+ result += "-#{selection_to_s(selection[:not])}" if selection[:not]
45
+ result
46
+ end
47
+
48
+ def match_criteria(criteria, data)
49
+ tree = self.new.parse(criteria)
50
+ return true if tree.is_a? String
51
+ tree = [tree] unless tree.is_a? Array
52
+ tree.map {|selection| match_selection(selection, data)}.any?
53
+ end
54
+
55
+ def match_selection(selection, data)
56
+ must_match = selection[:must].to_s.split('')
57
+ return false unless must_match == (must_match & data)
58
+ one_of = selection[:one_of].to_s.split('')
59
+ return false unless one_of.empty? || (one_of & data).any?
60
+ only_one_of = selection[:only_one_of].to_s.split('')
61
+ return false unless only_one_of.empty? || (only_one_of & data).size != 1
62
+ return false if match_selection(selection[:not], data) if selection[:not]
63
+ true
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end