eeml 0.0.1 → 0.0.2

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.
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <eeml>
3
+ <environment>
4
+ <title>Minimal</title>
5
+ <data id="0">
6
+ <value>36.2</value>
7
+ </data>
8
+ </environment>
9
+ </eeml>
@@ -163,6 +163,30 @@ class TestEnvironment < Test::Unit::TestCase
163
163
  assert_equal "36.2", datastream.value
164
164
  end
165
165
 
166
+ test "fails if no default namespace provided" do
167
+ assert_raise(MissingNamespace) {env = create_env_from_xml_file('no_namespace.xml')}
168
+ end
169
+
170
+ test "creates multiple environments from list xml" do
171
+ xml = File.read('test/data/list.xml')
172
+ list = Environment.new_list_from_eeml(xml)
173
+ assert 3, list.size
174
+ list.each do |obj|
175
+ assert obj.is_a? Environment
176
+ end
177
+ titles = list.map {|e| e.title}.sort
178
+ expected_titles = ["Badgerpower", "CurrentCost for house", "Power and Temperature"]
179
+ assert_equal expected_titles, titles
180
+ #TODO: check the environments fully (that no aliasing or other confusion has occurred in their parsing)
181
+ end
182
+
183
+ test "creates zero environments from list xml when has none" do
184
+ original_xml = File.read('test/data/list.xml')
185
+ xml = remove_nodes_called('environment', original_xml)
186
+ list = Environment.new_list_from_eeml(xml)
187
+ assert list.empty?, "should be empty list"
188
+ end
189
+
166
190
  def read_xml_file_one
167
191
  return File.read('test/data/doc_1.xml')
168
192
  end
@@ -246,20 +270,75 @@ class TestEnvironment < Test::Unit::TestCase
246
270
  assert_equal 'http://www.example.com/ourstudio/feeds/house.xml', env.feed_url
247
271
  end
248
272
 
249
- # --- ------------------------------------------------------------
250
- # --- json stuff ------------------------------------------------------------
251
- # --- ------------------------------------------------------------
273
+ # --- ------------------------------------------------------
274
+ # --- json input stuff ------------------------------------------------------
275
+ # --- ------------------------------------------------------
252
276
 
253
277
  test "creating Env obj from a JSON string" do
254
278
  env = create_env_from_json_file_one
255
279
  assert_not_nil env
256
280
  assert_instance_of Environment, env
281
+ assert_equal('title here', env.title)
282
+ assert_equal('description here', env.description)
283
+ assert_equal('http://example.com/api/1247.xml', env.feed_url)
284
+ assert_equal('http://example.com/studio/', env.website)
285
+ assert_equal('frozen', env.status)
286
+ assert_equal('someone@example.com', env.email)
287
+ assert_equal('http://example.com/some/icon.gif', env.icon)
288
+
289
+ #env attrs
290
+ assert_equal('1247', env.identifier)
291
+ assert_equal('2009-02-11T10:56:56Z', env.updated.strftime("%Y-%m-%dT%H:%M:%SZ"))
257
292
  end
258
293
 
294
+ test "location parses ok from json" do
295
+ env = create_env_from_json_file_one
296
+ assert_not_nil env.location
297
+ location = env.location
298
+ assert_equal "Up on the roof (somewhere)", location.name
299
+ assert_equal "50.1", location.latitude
300
+ assert_equal "48.7", location.longitude
301
+ assert_equal "1.34", location.elevation
302
+ assert_equal "physical", location.domain
303
+ assert_equal "outdoor", location.exposure
304
+ assert_equal "mobile", location.disposition
305
+ end
259
306
 
260
- # --- -------------------------------------------------------------
261
- # --- csv stuff -------------------------------------------------------------
262
- # --- -------------------------------------------------------------
307
+ test "datastreams parse ok from json" do
308
+ env = create_env_from_json_file_one
309
+ assert_equal 3, env.datastreams.size
310
+
311
+ #the expected values for the datastreams in the test doc
312
+ expectations_list = [
313
+ #id, tag array, min, max, value, unit_symbol, unit_type, unit_value
314
+ ['0', ['tagD0'], '-9999.0', '1022.0', '0', 'C', 'basicSI', 'Celsius'],
315
+ ['1', [], '0.0', '1023.0', '33', nil, nil, nil],
316
+ ['2', ['tagD2a', 'tagD2b', 'tagD2c'], '23.4', '1021.0', '42.1', nil, nil, nil]
317
+ ]
318
+ env.datastreams.each_with_index do |ds, i|
319
+
320
+ e_identifier, e_tags, e_min_value, e_max_value, e_value, e_unit_symbol, e_unit_type, e_unit_value = expectations_list[i]
321
+
322
+ assert_equal e_identifier, ds.identifier
323
+
324
+ assert_equal e_tags.size, ds.tags.size, "should have right num of tags"
325
+
326
+ e_tags.each do |expected_tag|
327
+ ds.tags.member? expected_tag
328
+ end
329
+
330
+ assert_equal e_min_value, ds.min_value
331
+ assert_equal e_max_value, ds.max_value
332
+ assert_equal e_value, ds.value
333
+ assert_equal e_unit_symbol, ds.unit_symbol
334
+ assert_equal e_unit_type, ds.unit_type
335
+ assert_equal e_unit_value, ds.unit_value
336
+ end
337
+ end
338
+
339
+ # --- -------------------------------------------------------
340
+ # --- csv input stuff -------------------------------------------------------
341
+ # --- -------------------------------------------------------
263
342
 
264
343
  def create_env_with_datastream_values(values)
265
344
  e = Environment.new
@@ -305,9 +384,10 @@ class TestEnvironment < Test::Unit::TestCase
305
384
  env.update_datastreams_from_csv_values!(values)
306
385
  assert_equal values, env.values_quick
307
386
  end
308
- # --- ----------------------------------------------------------
309
- # --- output stuff ----------------------------------------------------------
310
- # --- ----------------------------------------------------------
387
+
388
+ # --- -----------------------------------------------------
389
+ # --- eeml output stuff -----------------------------------------------------
390
+ # --- -----------------------------------------------------
311
391
 
312
392
  test "should output to xml ok" do
313
393
  env = create_env_from_xml_file_one
@@ -331,7 +411,58 @@ class TestEnvironment < Test::Unit::TestCase
331
411
  assert_equal expected_xml, output_xml
332
412
  end
333
413
 
414
+ # --- -----------------------------------------------------
415
+ # --- json output stuff -----------------------------------------------------
416
+ # --- -----------------------------------------------------
417
+ #DEV NOTE: use jsondiff tool to visual-diff expected and actual json http://tlrobinson.net/projects/js/jsondiff/
418
+
419
+ #TODO: decide what trailing whitespace should be output after json, and eeml, and correct tests
420
+ test "basic output in public json format" do
421
+ input_xml = File.read('test/data/doc_2.xml')
422
+ env = create_env_from_xml_string(input_xml)
423
+ output_json = env.to_json
424
+ expected_json = File.read('test/data/doc_2_expected.json').rstrip
425
+ expected_hash = JSON.parse(expected_json)
426
+ output_hash = JSON.parse(output_json)
427
+ assert_equal(expected_hash, output_hash)
428
+ end
334
429
 
430
+ test "basic output in public json format - no location" do
431
+ input_xml = File.read('test/data/doc_2.xml')
432
+ input_xml = remove_first_node_called('location', input_xml)
433
+ env = create_env_from_xml_string(input_xml)
434
+ output_json = env.to_json
435
+ output_hash = JSON.parse(output_json)
436
+
437
+ expected_json = File.read('test/data/doc_2_expected.json')
438
+ expected_hash = JSON.parse(expected_json)
439
+ assert_not_nil expected_hash.delete("location")
440
+ assert_json_hashes_equal(expected_hash, output_hash)
441
+ end
442
+
443
+ test "basic output in public json format - location but no latitude" do
444
+ input_xml = File.read('test/data/doc_2.xml')
445
+ input_xml = remove_first_node_called('lat', input_xml)
446
+ env = create_env_from_xml_string(input_xml)
447
+ actual_json = env.to_json
448
+ actual_hash = JSON.parse(actual_json)
449
+
450
+ assert_nil env.location.latitude
451
+ expected_json = File.read('test/data/doc_2_expected.json')
452
+ expected_hash = JSON.parse(expected_json)
453
+ expected_hash["location"].delete("lat")
454
+ #File.open('tmp_expected.json', 'w') {|f| f.write expected_hash.to_json }
455
+ #File.open('tmp_actual.json', 'w') {|f| f.write actual_hash.to_json }
456
+
457
+ assert_json_hashes_equal(expected_hash, actual_hash)
458
+ end
459
+
460
+ test "basic output in public json format - minimal env" do
461
+ env = Environment.new
462
+ assert_nil env.identifier
463
+ output_json = env.to_json
464
+ assert_not_nil output_json
465
+ end
335
466
 
336
467
  # --- convenience stuff - don't put tests under here ------------------------------
337
468
 
@@ -366,5 +497,12 @@ class TestEnvironment < Test::Unit::TestCase
366
497
  return Environment.new_from_json(json)
367
498
  end
368
499
 
500
+ def prep_json_for_reading(json)
501
+ return nil if json.nil?
502
+ json.gsub(/","/, '"' + "\n" + '"').sort
503
+ end
504
+
505
+
506
+
369
507
 
370
508
  end
data/test/test_helper.rb CHANGED
@@ -5,13 +5,12 @@ require 'test/libxml_test_helper'
5
5
  # Thought a mock library will be useful for testing out any stuff that
6
6
  # does any http-ing, but have no strong feelings about which one to use.
7
7
  # Looking at the syntax of each of the libraries, I liked the look of the
8
- # mocha syntax more, so was thinking to use that when required.
8
+ # mocha syntax more, so was thinking to use that when/if required.
9
9
  #
10
10
  # require 'flexmock'
11
11
  require 'mocha'
12
12
 
13
13
 
14
-
15
14
  #consider adding custom assertions to clean code up
16
15
  #http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html
17
16
 
@@ -47,10 +46,71 @@ class Test::Unit::TestCase
47
46
  out
48
47
  end
49
48
 
49
+ #compare not the given json strings directly but their hash structures after parsing.
50
+ #also try to give a more concise diff, if they are different, using Hash.diff from activesupport
51
+ def assert_json_strings_equal(expected_string, actual_string, message=nil)
52
+ expected_structure = JSON.parse(expected_string)
53
+ actual_structure = JSON.parse(actual_string)
54
+
55
+ diff = expected_structure.diff(actual_structure)
56
+ diff_string = diff.inspect.gsub(/"/, "'")
57
+ full_message = build_message(message, "Parsed JSON structure doesn't match expected. Hash Diff (quotes changed): <?>\n" +
58
+ "Full text: Expected: \n<?>\nbut was: <?>.\n",
59
+ diff_string, expected_string, actual_string)
60
+ assert_block(full_message) do
61
+ expected_structure == actual_structure
62
+ end
63
+ #File.open('tmp.json', 'w') {|f| f.write output_json }
64
+ #File.open('tmp_split.json', 'w') {|f| f.write prep_json_for_reading(output_json) }
65
+ #File.open('tmp_expected_split.json', 'w') {|f| f.write prep_json_for_reading(expected_json)}
66
+
67
+ #TODO: consider allowing submission of both to a json visual diff app, too. (only if switched on by an environment variable).
68
+ end
69
+
70
+ def assert_json_hashes_equal(expected_structure, actual_structure, message=nil)
71
+ diff = expected_structure.diff(actual_structure)
72
+ diff_string = diff.inspect.gsub(/"/, "'")
73
+ full_message = build_message(message, "JSON structure doesn't match expected. Hash Diff (quotes changed): <?>\n" +
74
+ "Full values: Expected: \n<?>\nbut was: <?>.\n", diff_string, expected_structure.inspect, actual_structure.inspect)
75
+ assert_block(full_message) do
76
+ expected_structure == actual_structure
77
+ end
78
+ end
79
+
50
80
  end
51
81
 
82
+
83
+
84
+ #TODO: don't add this Hash.diff(h2) for all hashes, only for ones we want to diff (e.g. on the fly during assert_json_strings_equal)
85
+ #TODO: check rails license
86
+ module ASCoreExtensions #was ActiveSupport
87
+ module Hash #:nodoc:
88
+ module Diff
89
+ # Returns a hash that represents the difference between two hashes.
90
+ #
91
+ # Examples:
92
+ #
93
+ # {1 => 2}.diff(1 => 2) # => {}
94
+ # {1 => 2}.diff(1 => 3) # => {1 => 2}
95
+ # {}.diff(1 => 2) # => {1 => 2}
96
+ # {1 => 2, 3 => 4}.diff(1 => 2) # => {3 => 4}
97
+ def diff(h2)
98
+ self.dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| self.has_key?(k) })
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class Hash #:nodoc:
105
+ include ASCoreExtensions::Hash::Diff
106
+ end
107
+
108
+
109
+
52
110
  $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
53
111
 
54
112
  require 'eeml'
55
113
 
56
114
  include Eeml
115
+
116
+
@@ -6,4 +6,7 @@ class TestLibXMLEemlParserV005 < Test::Unit::TestCase
6
6
  #p.make_environment_from_xml('bad')
7
7
  end
8
8
 
9
+ implement "re-populates env if env given" do
10
+ end
11
+
9
12
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eeml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neill Bogie, Sam Mulube
@@ -30,7 +30,7 @@ cert_chain:
30
30
  yyRwZdVyDdsafg==
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2009-04-17 00:00:00 +01:00
33
+ date: 2009-05-05 00:00:00 +01:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -57,7 +57,7 @@ dependencies:
57
57
  version: "0"
58
58
  - - "="
59
59
  - !ruby/object:Gem::Version
60
- version: 1.1.3
60
+ version: 1.1.4
61
61
  version:
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rake
@@ -97,15 +97,14 @@ extra_rdoc_files:
97
97
  - README
98
98
  - lib/eeml.rb
99
99
  - lib/eeml/constants.rb
100
- - lib/eeml/feed_retriever.rb
101
- - lib/eeml/json_environment_parser.rb
100
+ - lib/eeml/json_environment_parser_v005.rb
102
101
  - lib/eeml/output_registry.rb
103
102
  - lib/eeml/parser_registry.rb
104
103
  - lib/eeml/libxml_eeml_output_v005.rb
105
- - lib/eeml/feed_output.rb
106
104
  - lib/eeml/libxml_eeml_parser_v005.rb
107
105
  - lib/eeml/exceptions.rb
108
106
  - lib/eeml/csv_parser.rb
107
+ - lib/eeml/json_output.rb
109
108
  - lib/eeml/environment.rb
110
109
  - lib/blank.rb
111
110
  files:
@@ -120,20 +119,23 @@ files:
120
119
  - test/test_libxml_eeml_parser_v005.rb
121
120
  - test/test_helper.rb
122
121
  - test/data/minimal.xml
122
+ - test/data/doc_2_expected.json
123
+ - test/data/list.xml
123
124
  - test/data/out_empty.xml
125
+ - test/data/no_namespace.xml
124
126
  - test/data/doc_1.xml
125
127
  - test/data/doc_1.json
128
+ - test/data/doc_2.xml
126
129
  - lib/eeml.rb
127
130
  - lib/eeml/constants.rb
128
- - lib/eeml/feed_retriever.rb
129
- - lib/eeml/json_environment_parser.rb
131
+ - lib/eeml/json_environment_parser_v005.rb
130
132
  - lib/eeml/output_registry.rb
131
133
  - lib/eeml/parser_registry.rb
132
134
  - lib/eeml/libxml_eeml_output_v005.rb
133
- - lib/eeml/feed_output.rb
134
135
  - lib/eeml/libxml_eeml_parser_v005.rb
135
136
  - lib/eeml/exceptions.rb
136
137
  - lib/eeml/csv_parser.rb
138
+ - lib/eeml/json_output.rb
137
139
  - lib/eeml/environment.rb
138
140
  - lib/blank.rb
139
141
  - schemas/eeml/005.xsd
metadata.gz.sig CHANGED
@@ -1,3 +1 @@
1
- (ѭ�س�
2
- A���5jj�Bh�k_�G�F�ȴ'*KLY�|4��Q��
3
- ��<R���5 7z>ӱ�|�|]m��E:��a�.{�ҹ�J��h:�C�C�Է��DT���д���w�^d^
1
+ >�t�{��� ��)g�Bcg�T8�Z"B��.���C釴�d��3����M |�����I����uJ��Z�����Z%t4y��jM�����9 �=4<�+W���Y��l��M��et^>puEz�J4���?@�Mn\�kR�1���)�/�ʶTM y{��mb��J71_&v��5&�g�ˡ�l���JJ�v���c�؏oY�w���d� wN�9�[��Z����8S1�<wC�p�@�'�.�I�X�"X���B}�
@@ -1,169 +0,0 @@
1
- module FeedOutput # :nodoc:
2
- #TODO: move away from mixins for this functionality.
3
- #TODO: This is v005-specific.
4
- module EnvironmentNode # :nodoc:
5
- include LibXML
6
- #assumes a logger()
7
- #assumes retrieved_at()
8
-
9
- #TODO: Move these (now unused) methods to the publisher (e.g. a rails controller?) which will decide where it's going to host the env,
10
- # and which will set the feed property accordingly before serialising the env.
11
- # def public_feed_url
12
- # return "http://#{DEFAULT_HOST}/api/#{self.id}.xml"
13
- # end
14
-
15
- # def public_csv_url
16
- # return "http://#{DEFAULT_HOST}/api/#{self.id}.csv"
17
- # end
18
-
19
- # def public_json_url
20
- # return "http://#{DEFAULT_HOST}/api/#{self.id}.json"
21
- # end
22
-
23
-
24
- def create_eeml_document
25
- doc = XML::Document.new
26
- eeml = doc.root = XML::Node.new('eeml')
27
- XML::Namespace.new(eeml, nil, Eeml::EEML_HREF)
28
- XML::Namespace.new(eeml, 'xsi', Eeml::XSI_NAMESPACE)
29
- eeml['version'] = Eeml::EEML_VERSION
30
- eeml['xsi:schemaLocation'] = Eeml::EEML_SCHEMA_LOCATION
31
- return doc
32
- end
33
-
34
- # Create a csv representation of this environment by iterating through all datastreams and returning
35
- # their values.
36
- def to_csv
37
- return self.datastreams.map { |d| d.value }.join(",")
38
- end
39
-
40
- # Create an xml representation of this environment. The document returned should be valid EEML.
41
- # def to_eeml(options = { :full => true })
42
- # # Returns the public feed URL for this environment.
43
-
44
-
45
- # logger.debug("*** Returning eeml representation of environment: #{self.identifier}")
46
-
47
- # doc = create_eeml_document
48
-
49
- # doc.root << to_xml_node(options)
50
-
51
- # return doc.to_s(:encoding => XML::Encoding::UTF_8)
52
- # end
53
-
54
- def to_xml_node_old(options = { :full => true })
55
- logger.debug("*** Creating xml node for environment: #{self.identifier}")
56
-
57
- environment_node = XML::Node.new('environment')
58
- #TODO: this was retrieved_at in the db, but it's 'updated' in the xml. Clarify w sam...
59
- # ... env.retrieved_at doesn't make much sense to clients generating eeml using the gem.
60
- environment_node['updated'] = self.updated.strftime(XML_TIME_FORMAT_STRING) unless self.updated.nil?
61
- environment_node['id'] = self.identifier.to_s unless self.identifier.blank?
62
- #TODO: write all these strings out safely for xml
63
- environment_node['creator'] = self.creator.to_s unless self.creator.blank?
64
-
65
- #TODO: these all should really appear, even when absent? likely make conditional.
66
- unless self.title.blank?
67
- environment_node << title_node = XML::Node.new('title')
68
- title_node << self.title
69
- end
70
-
71
- unless self.feed_url.blank?
72
- environment_node << feed_node = XML::Node.new('feed')
73
- feed_node << self.feed_url
74
- end
75
-
76
- unless self.status.blank?
77
- environment_node << status_node = XML::Node.new('status')
78
- status_node << self.status
79
- end
80
-
81
- unless self.description.blank?
82
- environment_node << description_node = XML::Node.new('description')
83
- description_node << self.description
84
- end
85
-
86
- unless self.icon.blank?
87
- environment_node << icon_node = XML::Node.new('icon')
88
- icon_node << self.icon
89
- end
90
-
91
- unless self.website.blank?
92
- environment_node << website_node = XML::Node.new('website')
93
- website_node << self.website
94
- end
95
-
96
- unless self.email.blank?
97
- environment_node << email_node = XML::Node.new('email')
98
- email_node << self.email
99
- end
100
-
101
- unless self.location.nil?
102
- environment_node << location_node = XML::Node.new('location')
103
- location_node['domain'] = self.location.domain
104
- location_node['exposure'] = self.location.exposure unless self.location.exposure.blank?
105
- location_node['disposition'] = self.location.disposition unless self.location.disposition.blank?
106
-
107
- unless self.location.name.blank?
108
- location_node << location_name_node = XML::Node.new('name')
109
- location_name_node << self.location.name
110
- end
111
-
112
- location_node << lat_node = XML::Node.new('lat')
113
- lat_node << self.location.latitude
114
-
115
- location_node << lng_node = XML::Node.new('lon')
116
- lng_node << self.location.longitude
117
-
118
- unless self.location.elevation.blank?
119
- location_node << elevation_node = XML::Node.new('ele')
120
- elevation_node << self.location.elevation
121
- end
122
- end
123
-
124
- if options[:full] == true
125
- self.datastreams.each do |datastream|
126
- environment_node << datastream.to_xml_node unless datastream.nil?
127
- end
128
- end
129
-
130
- return environment_node
131
- end
132
- end
133
-
134
-
135
-
136
- module DataStreamNode # :nodoc:
137
- include LibXML
138
- # Create and return an XML::Node object representing this datastream. This method creates all
139
- # required child nodes of the datastream object, including the list of tag elements, any units element
140
- # and the value.
141
- def to_xml_node
142
- datastream_node = XML::Node.new('data')
143
- datastream_node['id'] = self.identifier.to_s
144
-
145
- self.tags.each do |tag|
146
- tag_node = XML::Node.new('tag')
147
- tag_node << tag
148
- datastream_node << tag_node
149
- end
150
-
151
- datastream_node << value_node = XML::Node.new('value')
152
-
153
- value_node['minValue'] = self.min_value.to_s unless self.min_value.to_s.empty?
154
- value_node['maxValue'] = self.max_value.to_s unless self.max_value.to_s.empty?
155
-
156
- value_node << self.value.to_s
157
-
158
- unless self.unit_value.to_s.empty? && self.unit_type.to_s.empty? && self.unit_symbol.to_s.empty?
159
- datastream_node << unit_node = XML::Node.new('unit')
160
- unit_node['type'] = self.unit_type.to_s unless self.unit_type.to_s.empty?
161
- unit_node['symbol'] = self.unit_symbol.to_s unless self.unit_symbol.to_s.empty?
162
- unit_node << self.unit_value.to_s unless self.unit_value.to_s.empty?
163
- end
164
-
165
- return datastream_node
166
- end
167
- end
168
-
169
- end
@@ -1,103 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
- module Eeml
4
-
5
- class FeedRetriever
6
-
7
- DEFAULT_TIMEOUT = 5
8
- PREMIUM_ENVIRONMENT_AGE = raise 3
9
-
10
- attr_accessor :retrieval_errors #will hold an array of string error messages populated during feed retrieval. currently populated only in fetch_remote_data
11
- attr_accessor :logger
12
- attr_accessor :feed_url, :retrieved_at
13
- attr_accessor :feed_changed, :feed_retrieved
14
- attr_accessor :feed_content, :mime_type
15
-
16
- def initialize
17
- end
18
-
19
- # only attempt to retrieve data if request is after our minimum time delta
20
- #currently makes use of get_response() and fetch() to do actual retrieval.
21
- def fetch_remote_data
22
- @retrieval_errors = []
23
- logger.debug("*** Attempting to fetch remote data")
24
-
25
- # only attempt to retrieve data if this environment has a feed_url
26
- if !self.feed_url.blank? && (self.retrieved_at.nil? || (Time.now.utc - self.retrieved_at.utc) > PREMIUM_ENVIRONMENT_AGE)
27
- logger.debug("*** Our refresh delta has passed so retrieve remote data")
28
-
29
- self.feed_changed = false
30
- self.feed_retrieved = false
31
-
32
- response = get_response
33
-
34
- case response
35
- when Net::HTTPSuccess
36
- logger.debug("*** 200 ok... checking mime type #{response.content_type}.")
37
- if MIME_TYPES.include?(response.content_type)
38
- logger.debug("*** We have a valid mime type")
39
-
40
- self.feed_content = response.body.to_s.strip
41
- self.mime_type = response.content_type
42
-
43
- self.retrieved_at = Time.now.utc.to_s(:db)
44
- else
45
- logger.debug("*** wrong mime-type.")
46
- white_list = ['text/html', 'text/javascript', 'application/javascript'] # acceptably WRONG header values.
47
- filtered_advice = ( white_list.member?(response.content_type) ? " Got '#{response.content_type}'." : "" )
48
- @retrieval_errors << "Wrong mime-type. Need application/xml, text/csv, or variants." + filtered_advice
49
- end
50
- else
51
- self.feed_retrieved = false
52
- self.feed_changed = false
53
- logger.debug("*** Unable to fetch remote data")
54
- end
55
- else
56
- logger.debug("*** No feed url present or refresh delta not yet expired - don't do nothin")
57
- # TODO remove after development
58
- end
59
- rescue URI::InvalidURIError, Timeout::Error, SystemCallError => e
60
- self.feed_retrieved = false
61
- self.feed_changed = false
62
- @retrieval_errors << "Url bad or unavailable."
63
- logger.error("*** Error retrieving feed from remote source: #{e}")
64
- end
65
-
66
- # private
67
-
68
- # separating this method out makes mocking our response fairly simple
69
- # basically we just create a dummy response object, and override this
70
- # method with a stubbed version that returns our dummy response
71
- def get_response
72
- return fetch(feed_url)
73
- end
74
-
75
- # TODO: update test specs so this passes properly
76
- # this fetch method recursively follows redirections up to a maximum depth of 10 redirections
77
- def fetch(uri_str, limit = 10)
78
- uri = create_uri(uri_str)
79
-
80
- logger.debug("*** Fetching content from :#{uri}")
81
- http_client = Net::HTTP.new(uri.host, uri.port)
82
-
83
- # the default timeout appears to be 60 seconds. this is very long
84
- # override it to be 5 seconds
85
- http_client.open_timeout = DEFAULT_TIMEOUT
86
- http_client.read_timeout = DEFAULT_TIMEOUT
87
- response = http_client.request_get(uri.request_uri)
88
- logger.debug("*** Got response: #{response}")
89
- case response
90
- when Net::HTTPSuccess then response
91
- when Net::HTTPRedirection then fetch(response['location'], limit - 1)
92
- else response
93
- end
94
- end
95
-
96
- def create_uri(uri_str)
97
- logger.debug("*** Creating uri from: #{uri_str}")
98
- uri = URI.parse(uri_str)
99
- raise URI::InvalidURIError unless uri.is_a?(URI::HTTP) or uri.is_a?(URI::HTTPS)
100
- return uri
101
- end
102
- end
103
- end
@@ -1,11 +0,0 @@
1
- module Eeml
2
- #a parser for json environments
3
- class JsonEnvironmentParser
4
- def make_environment_from_json(json_str)
5
- env = Environment.new
6
- return env
7
- end
8
- end
9
- end
10
-
11
-