bel_parser 1.0.0.alpha.12 → 1.0.0.alpha.13

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gemspec +1 -1
  3. data/VERSION +1 -1
  4. data/bin/bel2_validator +35 -8
  5. data/lib/bel_parser/expression/validator.rb +3 -2
  6. data/lib/bel_parser/language/apply_namespace_encoding.rb +96 -0
  7. data/lib/bel_parser/language/base_specification.rb +82 -0
  8. data/lib/bel_parser/language/expression_validator.rb +6 -2
  9. data/lib/bel_parser/language/relationship.rb +1 -1
  10. data/lib/bel_parser/language/semantics/signature_mapping.rb +26 -32
  11. data/lib/bel_parser/language/semantics_ast.rb +285 -149
  12. data/lib/bel_parser/language/semantics_ast_warnings.rb +180 -0
  13. data/lib/bel_parser/language/semantics_result.rb +11 -2
  14. data/lib/bel_parser/language/semantics_type_warning.rb +22 -0
  15. data/lib/bel_parser/language/semantics_warning.rb +8 -0
  16. data/lib/bel_parser/language/specification.rb +38 -55
  17. data/lib/bel_parser/language/syntax/undefined_namespace_value.rb +43 -0
  18. data/lib/bel_parser/language/syntax_error.rb +8 -0
  19. data/lib/bel_parser/language/syntax_result.rb +8 -0
  20. data/lib/bel_parser/language/syntax_warning.rb +9 -4
  21. data/lib/bel_parser/language/version1_0/functions/abundance.rb +5 -6
  22. data/lib/bel_parser/language/version1_0/functions/biological_process.rb +5 -6
  23. data/lib/bel_parser/language/version1_0/functions/complex_abundance.rb +6 -7
  24. data/lib/bel_parser/language/version1_0/functions/fusion.rb +39 -60
  25. data/lib/bel_parser/language/version1_0/functions/gene_abundance.rb +9 -12
  26. data/lib/bel_parser/language/version1_0/functions/list.rb +5 -6
  27. data/lib/bel_parser/language/version1_0/functions/micro_rna_abundance.rb +5 -6
  28. data/lib/bel_parser/language/version1_0/functions/pathology.rb +5 -6
  29. data/lib/bel_parser/language/version1_0/functions/protein_abundance.rb +16 -30
  30. data/lib/bel_parser/language/version1_0/functions/protein_modification.rb +15 -27
  31. data/lib/bel_parser/language/version1_0/functions/rna_abundance.rb +8 -11
  32. data/lib/bel_parser/language/version1_0/functions/substitution.rb +6 -12
  33. data/lib/bel_parser/language/version1_0/functions/translocation.rb +9 -12
  34. data/lib/bel_parser/language/version1_0/functions/truncation.rb +2 -4
  35. data/lib/bel_parser/language/version1_0/value_encodings/abundance.rb +21 -0
  36. data/lib/bel_parser/language/version1_0/value_encodings/any.rb +74 -0
  37. data/lib/bel_parser/language/version1_0/value_encodings/biological_process.rb +21 -0
  38. data/lib/bel_parser/language/version1_0/value_encodings/complex_abundance.rb +21 -0
  39. data/lib/bel_parser/language/version1_0/value_encodings/gene_abundance.rb +21 -0
  40. data/lib/bel_parser/language/version1_0/value_encodings/micro_rna_abundance.rb +21 -0
  41. data/lib/bel_parser/language/version1_0/value_encodings/pathology.rb +21 -0
  42. data/lib/bel_parser/language/version1_0/value_encodings/protein_abundance.rb +21 -0
  43. data/lib/bel_parser/language/version1_0/value_encodings/rna_abundance.rb +21 -0
  44. data/lib/bel_parser/language/version1_0.rb +6 -87
  45. data/lib/bel_parser/language/version2_0/functions/abundance.rb +13 -18
  46. data/lib/bel_parser/language/version2_0/functions/biological_process.rb +5 -6
  47. data/lib/bel_parser/language/version2_0/functions/complex_abundance.rb +9 -12
  48. data/lib/bel_parser/language/version2_0/functions/fragment.rb +4 -9
  49. data/lib/bel_parser/language/version2_0/functions/from_location.rb +5 -6
  50. data/lib/bel_parser/language/version2_0/functions/fusion.rb +39 -66
  51. data/lib/bel_parser/language/version2_0/functions/gene_abundance.rb +13 -18
  52. data/lib/bel_parser/language/version2_0/functions/list.rb +5 -6
  53. data/lib/bel_parser/language/version2_0/functions/location.rb +5 -6
  54. data/lib/bel_parser/language/version2_0/functions/micro_rna_abundance.rb +13 -18
  55. data/lib/bel_parser/language/version2_0/functions/molecular_activity.rb +6 -5
  56. data/lib/bel_parser/language/version2_0/functions/pathology.rb +5 -6
  57. data/lib/bel_parser/language/version2_0/functions/protein_abundance.rb +21 -30
  58. data/lib/bel_parser/language/version2_0/functions/protein_modification.rb +11 -17
  59. data/lib/bel_parser/language/version2_0/functions/rna_abundance.rb +13 -18
  60. data/lib/bel_parser/language/version2_0/functions/to_location.rb +5 -6
  61. data/lib/bel_parser/language/version2_0/functions/variant.rb +1 -4
  62. data/lib/bel_parser/language/version2_0/value_encodings/abundance.rb +21 -0
  63. data/lib/bel_parser/language/version2_0/value_encodings/activity.rb +21 -0
  64. data/lib/bel_parser/language/version2_0/value_encodings/any.rb +74 -0
  65. data/lib/bel_parser/language/version2_0/value_encodings/biological_process.rb +21 -0
  66. data/lib/bel_parser/language/version2_0/value_encodings/complex_abundance.rb +21 -0
  67. data/lib/bel_parser/language/version2_0/value_encodings/gene_abundance.rb +21 -0
  68. data/lib/bel_parser/language/version2_0/value_encodings/location.rb +21 -0
  69. data/lib/bel_parser/language/version2_0/value_encodings/micro_rna_abundance.rb +21 -0
  70. data/lib/bel_parser/language/version2_0/value_encodings/pathology.rb +21 -0
  71. data/lib/bel_parser/language/version2_0/value_encodings/protein_abundance.rb +21 -0
  72. data/lib/bel_parser/language/version2_0/value_encodings/protein_modification.rb +21 -0
  73. data/lib/bel_parser/language/version2_0/value_encodings/rna_abundance.rb +21 -0
  74. data/lib/bel_parser/language/version2_0.rb +6 -60
  75. data/lib/bel_parser/language.rb +3 -4
  76. data/lib/bel_parser/parsers/ast/node.rb +14 -2
  77. data/lib/bel_parser/{language/quoting.rb → quoting.rb} +0 -56
  78. data/lib/bel_parser/resource/concept.rb +56 -0
  79. data/lib/bel_parser/resource/concept_scheme.rb +35 -0
  80. data/lib/bel_parser/resource/dataset.rb +34 -0
  81. data/lib/bel_parser/resource/eager_reader.rb +75 -0
  82. data/lib/bel_parser/resource/eager_sparql_reader.rb +51 -0
  83. data/lib/bel_parser/resource/http_cache.rb +71 -0
  84. data/lib/bel_parser/resource/jena_tdb_reader.rb +246 -0
  85. data/lib/bel_parser/resource/lru_cache.rb +111 -0
  86. data/lib/bel_parser/resource/lru_reader.rb +38 -0
  87. data/lib/bel_parser/resource/reader.rb +18 -0
  88. data/lib/bel_parser/resource/resource_file_reader.rb +134 -0
  89. data/lib/bel_parser/resource/sparql_reader.rb +178 -0
  90. data/lib/bel_parser/resource/value.rb +31 -0
  91. metadata +42 -4
  92. data/lib/bel_parser/language/version1_0/syntax/function.rb +0 -28
@@ -0,0 +1,75 @@
1
+ require 'concurrent/hash'
2
+
3
+ module BELParser
4
+ module Resource
5
+ module EagerReader
6
+
7
+ EMPTY_ARRAY = [].freeze
8
+ CACHE_KEYS = [:name, :identifier, :title, :synonyms].freeze
9
+
10
+ def resources
11
+ @resources ||= Concurrent::Hash.new
12
+ end
13
+
14
+ def locks
15
+ @locks ||= Concurrent::Hash.new
16
+ end
17
+
18
+ def retrieve_resource(resource_identifier)
19
+ if !resources.key?(resource_identifier)
20
+ load_all_values(resource_identifier)
21
+ end
22
+ super
23
+ end
24
+
25
+ def retrieve_value_from_resource(resource_identifier, value)
26
+ if !resources.key?(resource_identifier)
27
+ load_all_values(resource_identifier)
28
+ end
29
+
30
+ concepts = resources[resource_identifier]
31
+ return super unless concepts
32
+ CACHE_KEYS.each do |key|
33
+ cached_concept = concepts[key].fetch(value, nil)
34
+ return cached_concept if cached_concept
35
+ end
36
+
37
+ EMPTY_ARRAY
38
+ end
39
+
40
+ def retrieve_values_from_resource(resource_identifier)
41
+ if !resources.key?(resource_identifier)
42
+ load_all_values(resource_identifier)
43
+ end
44
+
45
+ concepts = resources[resource_identifier]
46
+ return super unless concepts
47
+ concepts[:name].values
48
+ end
49
+
50
+ def load_all_values(identifier)
51
+ lock = locks[identifier] ||= Mutex.new
52
+ if lock.try_lock
53
+ Thread.new do
54
+ value_hash = {
55
+ :name => Hash.new { |hash, key| hash[key] = [] },
56
+ :identifier => Hash.new { |hash, key| hash[key] = [] },
57
+ :title => Hash.new { |hash, key| hash[key] = [] },
58
+ :synonyms => Hash.new { |hash, key| hash[key] = [] }
59
+ }
60
+ retrieve_values_from_resource(identifier).each do |concept|
61
+ value_hash[:name][concept.name] << concept
62
+ value_hash[:identifier][concept.identifier] << concept
63
+ value_hash[:title][concept.title] << concept
64
+ concept.synonyms.each do |synonym|
65
+ value_hash[:synonyms][synonym] << concept
66
+ end
67
+ end
68
+ resources[identifier] = value_hash
69
+ lock.unlock
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,51 @@
1
+ require 'concurrent/hash'
2
+
3
+ require_relative 'sparql_reader'
4
+
5
+ module BELParser
6
+ module Resource
7
+ # EagerSPARQLReader
8
+ class EagerSPARQLReader < SPARQLReader
9
+ def initialize(sparql_endpoint_url, validate_url = true)
10
+ @resources = Concurrent::Hash.new
11
+ @locks = Concurrent::Hash.new
12
+ super
13
+ end
14
+
15
+ def retrieve_resource(resource_identifier)
16
+ if @resources.key?(resource_identifier)
17
+ concepts = @resources[resource_identifier]
18
+ concepts[value]
19
+ else
20
+ lock = @locks[resource_identifier] ||= Mutex.new
21
+ if lock.try_lock
22
+ Thread.new do
23
+ concepts = retrieve_values_from_resource(resource_identifier).to_a
24
+ @resources[resource_identifier] =
25
+ Hash[
26
+ concepts.map do |c|
27
+ [c.name, c]
28
+ end
29
+ ]
30
+ lock.unlock
31
+ end
32
+ end
33
+
34
+ super
35
+ end
36
+ end
37
+
38
+ def retrieve_value_from_resource(resource_identifier, value)
39
+ concepts = @resources[resource_identifier]
40
+ return super unless concepts
41
+ concepts[value]
42
+ end
43
+
44
+ def retrieve_values_from_resource(resource_identifier)
45
+ concepts = @resources[resource_identifier]
46
+ return super unless concepts
47
+ concepts
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,71 @@
1
+ require 'base64'
2
+ require 'concurrent/hash'
3
+ require 'digest'
4
+ require 'fileutils'
5
+ require 'net/http'
6
+ require 'tempfile'
7
+
8
+ module BELParser
9
+ module Resource
10
+ class HTTPCache
11
+
12
+ # Lock (per URL) ensures concurrent retrieval/caching is thread-safe.
13
+ URL_LOCKS = Concurrent::Hash.new do |hash, key|
14
+ hash[key] = Mutex.new
15
+ end
16
+ private_constant :URL_LOCKS
17
+
18
+ def initialize(base_dir="#{Dir.tmpdir}/bel-resources")
19
+ @base_dir = FileUtils.mkdir_p(base_dir).first
20
+ end
21
+
22
+ def get(url)
23
+ cached_url_path = File.join(@base_dir, hash_url(url))
24
+ URL_LOCKS[url].synchronize do
25
+ if File.exists?(cached_url_path)
26
+ if block_given?
27
+ File.open(cached_url_path) do |cached_file|
28
+ yield cached_file
29
+ end
30
+ else
31
+ File.open(cached_url_path)
32
+ end
33
+ else
34
+ uri = URI.parse(url)
35
+ cached_file = File.open(cached_url_path, 'w')
36
+ begin
37
+ Net::HTTP.start(uri.host, uri.port) do |http|
38
+ http.request(Net::HTTP::Get.new(uri)) do |response|
39
+ if block_given?
40
+ response.read_body do |chunk|
41
+ cached_file.write(chunk)
42
+ yield StringIO.new(chunk)
43
+ end
44
+ else
45
+ content = response.read_body
46
+ cached_file.write(content)
47
+ return StringIO.new(content)
48
+ end
49
+ end
50
+ end
51
+ ensure
52
+ cached_file.close
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ protected
59
+
60
+ def hash_url(url)
61
+ Base64.encode64(Digest::SHA1.digest(url)).delete("/=\n")
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ if __FILE__ == $PROGRAM_NAME
68
+ BELParser::Resource::HTTPCache.new.get(ARGV.first) do |io|
69
+ io.each_line { |line| puts line }
70
+ end
71
+ end
@@ -0,0 +1,246 @@
1
+ require 'erb'
2
+ require 'rdf'
3
+ require 'rdf/vocab'
4
+ require 'rdf/jena'
5
+
6
+ require_relative 'reader'
7
+ require_relative 'lru_reader'
8
+ require_relative 'concept'
9
+ require_relative 'concept_scheme'
10
+
11
+ module BELParser
12
+ module Resource
13
+ class JenaTDBReader
14
+ include Reader
15
+ prepend LRUReader
16
+
17
+ BELV = RDF::Vocabulary.new('http://www.openbel.org/vocabulary/')
18
+ SKOS = RDF::Vocab::SKOS
19
+ DC = RDF::Vocab::DC
20
+ VALUE_PREDICATE_ORDER = [
21
+ SKOS.prefLabel,
22
+ DC.identifier,
23
+ DC.title,
24
+ SKOS.altLabel
25
+ ]
26
+
27
+ def initialize(tdb_directory_path)
28
+ @rdf = RDF::Jena::Repository.new(tdb_directory_path)
29
+ end
30
+
31
+ def retrieve_resource(identifier)
32
+ uri = RDF::URI(identifier)
33
+ domain, prefix, pref_label = nil
34
+ types = []
35
+ @rdf.query([:subject => uri]).each do |solution|
36
+ case solution.predicate
37
+ when RDF.type
38
+ types << solution.object
39
+ when BELV.domain
40
+ domain = solution.object.to_s
41
+ when BELV.prefix
42
+ prefix = solution.object.to_s
43
+ when SKOS.prefLabel
44
+ pref_label = solution.object.to_s
45
+ end
46
+ end
47
+ return nil unless types.any? do |type_uri|
48
+ type_uri == BELV.AnnotationConceptScheme || type_uri == BELV.NamespaceConceptScheme
49
+ end
50
+ ConceptScheme.new(uri, domain, prefix, pref_label, types)
51
+ end
52
+
53
+ def retrieve_value_from_resource(identifier, value)
54
+ concept_scheme = retrieve_resource(identifier)
55
+ return nil unless concept_scheme
56
+
57
+ template_binding = binding
58
+ sparql_query = RESOLVE_CONCEPT.result(template_binding)
59
+ to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme]
60
+
61
+ @rdf.query_execute(sparql_query).map(&to_concept)
62
+ end
63
+
64
+ def retrieve_values_from_resource(identifier)
65
+ concept_scheme = retrieve_resource(identifier)
66
+ return nil unless concept_scheme
67
+
68
+ template_binding = binding
69
+ sparql_query = RESOLVE_CONCEPTS.result(template_binding)
70
+ to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme]
71
+
72
+ @rdf.query_execute(sparql_query).map(&to_concept)
73
+ end
74
+
75
+ private
76
+
77
+ def find_value_uris(resource_uri, value)
78
+ VALUE_PREDICATE_ORDER.each do |predicate|
79
+ subjects =
80
+ @rdf.query([:predicate => predicate, :object => value])
81
+ .select do |stmt|
82
+ @rdf.has_statement?(
83
+ RDF::Statement(stmt.subject, SKOS.inScheme, resource_uri))
84
+ end.map(&:subject)
85
+
86
+ if !subjects.empty?
87
+ return subjects
88
+ end
89
+ end
90
+
91
+ []
92
+ end
93
+
94
+ def hash_to_concept(concept_scheme, hash)
95
+ Concept.new(concept_scheme,
96
+ *hash.values_at('concept', 'prefLabel', 'identifier', 'title',
97
+ 'altLabels', 'types'))
98
+ end
99
+
100
+ RESOLVE_CONCEPT = ERB.new(<<-SPARQL)
101
+ prefix belv: <http://www.openbel.org/vocabulary/>
102
+ prefix dct: <http://purl.org/dc/terms/>
103
+ prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
104
+ prefix skos: <http://www.w3.org/2004/02/skos/core#>
105
+ select ?concept ?prefLabel ?identifier ?title
106
+ (group_concat(distinct(?type);separator='|') as ?types)
107
+ (group_concat(distinct(?altLabel);separator='|') as ?altLabels)
108
+ where {
109
+ {?concept skos:prefLabel "<%= value %>"}
110
+ UNION
111
+ {?concept dct:identifier "<%= value %>"}
112
+ UNION
113
+ {?concept dct:title "<%= value %>"}
114
+ UNION
115
+ {?concept skos:altLabel "<%= value %>"}
116
+
117
+ ?concept skos:inScheme <<%= identifier %>> .
118
+ ?concept rdf:type ?type .
119
+
120
+ ?concept skos:prefLabel ?prefLabel .
121
+ ?concept dct:identifier ?identifier .
122
+ optional {
123
+ ?concept dct:title ?title .
124
+ ?concept skos:altLabel ?altLabel .
125
+ }
126
+ }
127
+ group by ?concept ?prefLabel ?identifier ?title
128
+ SPARQL
129
+
130
+ RESOLVE_CONCEPTS = ERB.new(<<-SPARQL)
131
+ prefix belv: <http://www.openbel.org/vocabulary/>
132
+ prefix dct: <http://purl.org/dc/terms/>
133
+ prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
134
+ prefix skos: <http://www.w3.org/2004/02/skos/core#>
135
+ select ?concept ?prefLabel ?identifier ?title
136
+ (group_concat(distinct(?type);separator='|') as ?types)
137
+ (group_concat(distinct(?altLabel);separator='|') as ?altLabels)
138
+ where {
139
+ ?concept skos:inScheme <<%= identifier %>> .
140
+ ?concept rdf:type ?type .
141
+ ?concept skos:prefLabel ?prefLabel .
142
+ optional {
143
+ ?concept dct:identifier ?identifier .
144
+ ?concept dct:title ?title .
145
+ ?concept skos:altLabel ?altLabel
146
+ }
147
+ }
148
+ group by ?concept ?prefLabel ?identifier ?title
149
+ SPARQL
150
+
151
+ #ConceptScheme
152
+ class ConceptScheme
153
+ include Dataset
154
+
155
+ attr_reader :identifier, :domain, :keyword, :name, :types
156
+
157
+ def initialize(uri, domain, prefix, name, types)
158
+ @identifier = uri
159
+ @domain = domain.to_s
160
+ @keyword = prefix.to_s
161
+ @name = name.to_s
162
+ @types = convert_types(types)
163
+ end
164
+
165
+ private
166
+
167
+ def convert_types(types)
168
+ types.map do |type|
169
+ case type
170
+ when BELV.NamespaceConceptScheme
171
+ Dataset::NAMESPACE
172
+ when BELV.AnnotationConceptScheme
173
+ Dataset::ANNOTATION
174
+ end
175
+ end.compact
176
+ end
177
+ end
178
+
179
+ class Concept
180
+ include Value
181
+
182
+ attr_reader :dataset, :uri, :name, :identifier,
183
+ :title, :synonyms, :encodings
184
+
185
+ def initialize(dataset, uri, pref_label, identifier,
186
+ title, alt_labels, types)
187
+
188
+ @dataset = dataset
189
+ @uri = uri
190
+ @name = pref_label.to_s
191
+ @identifier = identifier.to_s
192
+ @title = title.to_s
193
+ @synonyms =
194
+ if alt_labels.respond_to?(:each)
195
+ alt_labels.map(&:to_s)
196
+ else
197
+ alt_labels.to_s.split('|')
198
+ end
199
+ @encodings =
200
+ if types.respond_to?(:each)
201
+ convert_encoding_types(types.map(&:to_s))
202
+ else
203
+ convert_encoding_types(types.to_s.split('|'))
204
+ end
205
+ end
206
+
207
+ private
208
+
209
+ def convert_encoding_types(types)
210
+ types.map do |type|
211
+ case type
212
+ when BELV.AbundanceConcept
213
+ :A
214
+ when BELV.BiologicalProcessConcept
215
+ :B
216
+ when BELV.ComplexConcept
217
+ :C
218
+ when BELV.GeneConcept
219
+ :G
220
+ when BELV.LocationConcept
221
+ :L
222
+ when BELV.MicroRNAConcept
223
+ :M
224
+ when BELV.MolecularActivityConcept
225
+ :T
226
+ when BELV.PathologyConcept
227
+ :O
228
+ when BELV.ProteinConcept
229
+ :P
230
+ when BELV.ProteinModificationConcept
231
+ :E
232
+ when BELV.RNAConcept
233
+ :R
234
+ end
235
+ end.compact
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ if __FILE__ == $PROGRAM_NAME
243
+ reader = BELParser::Resource::JenaTDBReader.new(
244
+ '/home/tony/projects/openbel/resource-reasoner/biological-concepts-db')
245
+ reader.retrieve_resource('http://www.openbel.org/bel/namespace/hgnc-human-genes')
246
+ end
@@ -0,0 +1,111 @@
1
+ require 'concurrent/hash'
2
+
3
+ module BELParser
4
+ module Resource
5
+ # LRUCache implements a least recently used cache. This implementation was
6
+ # initially copied from https://github.com/SamSaffron/lru_redux.
7
+ class LRUCache
8
+ def initialize(max_size)
9
+ raise ArgumentError.new(:max_size) if max_size < 1
10
+
11
+ @max_size = max_size
12
+ @data = Concurrent::Hash.new
13
+ end
14
+
15
+ def max_size=(max_size)
16
+ max_size ||= @max_size
17
+
18
+ raise ArgumentError.new(:max_size) if max_size < 1
19
+
20
+ @max_size = max_size
21
+
22
+ @data.shift while @data.size > @max_size
23
+ end
24
+
25
+ def getset(key)
26
+ found = true
27
+ value = @data.delete(key){ found = false }
28
+ if found
29
+ @data[key] = value
30
+ else
31
+ result = @data[key] = yield
32
+ @data.shift if @data.length > @max_size
33
+ result
34
+ end
35
+ end
36
+
37
+ def fetch(key)
38
+ found = true
39
+ value = @data.delete(key){ found = false }
40
+ if found
41
+ @data[key] = value
42
+ else
43
+ yield if block_given?
44
+ end
45
+ end
46
+
47
+ def [](key)
48
+ found = true
49
+ value = @data.delete(key){ found = false }
50
+ if found
51
+ @data[key] = value
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def []=(key,val)
58
+ @data.delete(key)
59
+ @data[key] = val
60
+ @data.shift if @data.length > @max_size
61
+ val
62
+ end
63
+
64
+ def each
65
+ unless block_given?
66
+ return enum_for(:each)
67
+ end
68
+
69
+ array = @data.to_a
70
+ array.reverse!.each do |pair|
71
+ yield pair
72
+ end
73
+ end
74
+
75
+ # used further up the chain, non thread safe each
76
+ alias_method :each_unsafe, :each
77
+
78
+ def to_a
79
+ array = @data.to_a
80
+ array.reverse!
81
+ end
82
+
83
+ def delete(key)
84
+ @data.delete(key)
85
+ end
86
+
87
+ alias_method :evict, :delete
88
+
89
+ def key?(key)
90
+ @data.key?(key)
91
+ end
92
+
93
+ alias_method :has_key?, :key?
94
+
95
+ def clear
96
+ @data.clear
97
+ end
98
+
99
+ def count
100
+ @data.size
101
+ end
102
+
103
+ protected
104
+
105
+ # for cache validation only, ensures all is sound
106
+ def valid?
107
+ true
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'lru_cache'
2
+
3
+ module BELParser
4
+ module Resource
5
+ module LRUReader
6
+
7
+ LRU_MAX_SIZE = 500
8
+ private_constant :LRU_MAX_SIZE
9
+
10
+ def resources
11
+ @resources ||= Concurrent::Hash.new
12
+ end
13
+
14
+ def retrieve_resource(resource_identifier)
15
+ if !resources.key?(resource_identifier)
16
+ resources[resource_identifier] = LRUCache.new(LRU_MAX_SIZE)
17
+ end
18
+ super
19
+ end
20
+
21
+ def retrieve_value_from_resource(resource_identifier, value)
22
+ if !resources.key?(resource_identifier)
23
+ resources[resource_identifier] = LRUCache.new(LRU_MAX_SIZE)
24
+ end
25
+
26
+ concepts = resources[resource_identifier]
27
+ concepts.getset(value) {
28
+ puts "retrieving from RDF..."
29
+ super
30
+ }
31
+ end
32
+
33
+ def retrieve_values_from_resource(resource_identifier)
34
+ super
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module BELParser
2
+ module Resource
3
+ # Reader represents the API for a reader of resource data.
4
+ module Reader
5
+ def retrieve_resource(resource_identifier)
6
+ raise NotImplementedError, "#{__method__} is not implemented."
7
+ end
8
+
9
+ def retrieve_value_from_resource(resource_identifier, value)
10
+ raise NotImplementedError, "#{__method__} is not implemented."
11
+ end
12
+
13
+ def retrieve_values_from_resource(resource_identifier)
14
+ raise NotImplementedError, "#{__method__} is not implemented."
15
+ end
16
+ end
17
+ end
18
+ end