eeml 0.0.17 → 0.0.18

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.
data/.gitignore CHANGED
@@ -2,4 +2,4 @@ pkg
2
2
  doc
3
3
  eeml.gemspec
4
4
  client_config.yml
5
-
5
+ .*.swp
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ commit 9835edb290ef16b274d9ab59e3c6adca2ce97fcf
2
+ Author: Levent Ali <lebreeze@gmail.com>
3
+ Date: Wed Jul 7 18:48:34 2010 +0100
4
+
5
+ Version 0.0.18
6
+
7
+ json v1.0.0 changed to have current_value, min, max and at at top level within a datastream
8
+ Added eeml 0.5.1 parser
9
+
10
+
1
11
  commit 245dae9ae8e246d3f933106e70df4eadb33823fe
2
12
  Author: Levent Ali <lebreeze@gmail.com>
3
13
  Date: Fri Jul 2 16:03:27 2010 +0100
@@ -1,18 +1,49 @@
1
1
  module Eeml
2
2
  module Constants
3
- LOCAL_EEML5_SCHEMA_LOCATION = "schemas/eeml/005.xsd" # :nodoc:
4
- EEML5_HREF = "http://www.eeml.org/xsd/005"
5
- EEML5_VERSION = "5"
6
- EEML5_SCHEMA_LOCATION = "http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd"
3
+ # LOCAL_EEML5_SCHEMA_LOCATION = "schemas/eeml/005.xsd" # :nodoc:
4
+ # EEML5_HREF = "http://www.eeml.org/xsd/005"
5
+ # EEML5_VERSION = "5"
6
+ # EEML5_SCHEMA_LOCATION = "http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd"
7
7
 
8
- EEML5_NAMESPACE = ":#{EEML5_HREF}"
8
+ # EEML5_NAMESPACE = ":#{EEML5_HREF}"
9
9
  XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
10
10
 
11
- EEML6_VERSION = "0.6-alpha1"
11
+ # EEML6_VERSION = "0.6-alpha1"
12
12
 
13
13
  # Not calling this EEML as json is not part of the eeml spec
14
- JSON_1_0_0_VERSION = "1.0.0"
14
+ # JSON_1_0_0_VERSION = "1.0.0"
15
+
15
16
  # EEML6_RC1_VERSION = "0.6-rc1"
17
+ JSON_API = {}
18
+ EEML = {}
19
+
20
+ # This is what we called version 5
21
+ EEML["0.5.0"] =
22
+ {
23
+ :href => 'http://www.eeml.org/xsd/005',
24
+ :version => '5',
25
+ :schema_location => 'http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd'
26
+ }
27
+
28
+ # This is NEWER than version 5
29
+ EEML["0.5.1"] =
30
+ {
31
+ :href => 'http://www.eeml.org/xsd/0.5.1',
32
+ :version => '0.5.1',
33
+ :schema_location => 'http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd'
34
+ }
35
+
36
+ JSON_API["0.6-alpha"] =
37
+ {
38
+ :version => '0.6-alpha'
39
+ }
40
+
41
+ JSON_API["1.0.0"] =
42
+ {
43
+ :version => "1.0.0"
44
+ }
45
+
46
+
16
47
  end
17
48
  end
18
49
 
@@ -164,7 +164,7 @@ module Eeml
164
164
  end
165
165
  end
166
166
 
167
- def to_eeml(version = Constants::EEML5_VERSION)
167
+ def to_eeml(version = Constants::EEML['0.5.0'][:version])
168
168
  outputter = OutputRegistry.get_xml_output_for(version)
169
169
  outputter.to_eeml(self)
170
170
  end
@@ -1,4 +1,5 @@
1
1
  require 'eeml/libxml_eeml_parser_v005'
2
+ require 'eeml/libxml_eeml_parser_v051'
2
3
  require 'eeml/json_environment_parser_v005'
3
4
  require 'eeml/json_environment_parser_v006'
4
5
  require 'eeml/json_environment_parser_v100'
@@ -6,8 +7,19 @@ require 'eeml/json_environment_parser_v100'
6
7
  module Eeml
7
8
  class EnvironmentBuilder # :nodoc:
8
9
 
10
+ include LibXML
11
+
9
12
  def self.build_from_xml(xml_str)
10
- parser = LibXMLEemlParserV005.new
13
+ begin
14
+ xml = XML::Parser.string(xml_str).parse
15
+ if xml.root.namespaces.default.to_s == Constants::EEML['0.5.1'][:href]
16
+ parser = LibXMLEemlParserV051.new
17
+ else
18
+ parser = LibXMLEemlParserV005.new
19
+ end
20
+ rescue => e
21
+ parser = LibXMLEemlParserV005.new
22
+ end
11
23
  return parser.make_environment_from_xml(xml_str)
12
24
  end
13
25
 
@@ -18,14 +30,14 @@ module Eeml
18
30
 
19
31
  def self.build_from_json(json_str)
20
32
  json = JSON.parse(json_str)
21
- if json["version"].to_i == Constants::EEML5_VERSION.to_i
33
+ if json["version"].to_i == Constants::EEML['0.5.0'][:version].to_i
22
34
  parser = JsonEnvironmentParserV005.new
23
- elsif json["version"] == Constants::JSON_1_0_0_VERSION
35
+ elsif json["version"] == Constants::JSON_API['1.0.0'][:version]
24
36
  parser = JsonEnvironmentParserV100.new
25
- elsif json["version"].to_f == Constants::EEML6_VERSION.to_f
37
+ elsif json["version"].to_f == Constants::JSON_API['0.6-alpha'][:version].to_f
26
38
  parser = JsonEnvironmentParserV006.new
27
39
  else
28
- raise "Invalid version specification. Permitted versions are #{Constants::EEML5_VERSION}, #{Constants::EEML6_VERSION} and #{Constants::JSON_1_0_0_VERSION}"
40
+ raise "Invalid version specification. Permitted versions are #{Constants::EEML['0.5.0'][:version]}, #{Constants::JSON_API["0.6-alpha"][:version]} and #{Constants::JSON_API["1.0.0"][:version]}"
29
41
  end
30
42
  return parser.make_environment_from_hash(json)
31
43
  end
@@ -52,18 +52,18 @@ module Eeml
52
52
  datastream.identifier = datastream_hash['id']
53
53
  datastream.tags = datastream_hash['tags'] unless datastream_hash['tags'].nil?
54
54
 
55
- values_arr = datastream_hash["values"]
55
+ #values_arr = datastream_hash["history"]
56
56
 
57
- raise DataMissingValue if values_arr.nil?
57
+ #raise DataMissingValue if values_arr.nil?
58
58
 
59
- values_arr.each do |v|
60
- value = Value.new(:value => v["value"],
59
+ #values_arr.each do |v|
60
+ value = Value.new(:value => datastream_hash["current_value"],
61
61
  :min_value => datastream_hash["min_value"],
62
62
  :max_value => datastream_hash["max_value"],
63
- :recorded_at => v["at"])
63
+ :recorded_at => datastream_hash["at"])
64
64
 
65
65
  datastream.add_value(value)
66
- end
66
+ #end
67
67
 
68
68
  unit_hash = datastream_hash["unit"]
69
69
  unless unit_hash.nil?
@@ -16,7 +16,7 @@ module Eeml
16
16
  :website => environment.website,
17
17
  :email => environment.email,
18
18
  :icon => environment.icon,
19
- :version => EEML5_VERSION }
19
+ :version => EEML['0.5.0'][:version] }
20
20
 
21
21
  environment_hash[:updated] = environment.updated.utc.iso8601 unless environment.updated.nil? #TODO: was retrieved_at
22
22
 
@@ -6,10 +6,10 @@ module Eeml
6
6
  def to_eeml(environment)
7
7
  doc = XML::Document.new
8
8
  eeml = doc.root = XML::Node.new('eeml')
9
- XML::Namespace.new(eeml, nil, Constants::EEML5_HREF)
9
+ XML::Namespace.new(eeml, nil, Constants::EEML['0.5.0'][:href])
10
10
  XML::Namespace.new(eeml, 'xsi', Constants::XSI_NAMESPACE)
11
- eeml['version'] = Constants::EEML5_VERSION
12
- eeml['xsi:schemaLocation'] = Constants::EEML5_SCHEMA_LOCATION
11
+ eeml['version'] = Constants::EEML['0.5.0'][:version]
12
+ eeml['xsi:schemaLocation'] = Constants::EEML['0.5.0'][:schema_location]
13
13
  eeml << xml_node_for_environment(environment)
14
14
 
15
15
  return doc.to_s(:encoding => XML::Encoding::UTF_8)
@@ -0,0 +1,118 @@
1
+ module Eeml
2
+ class LibXMLEemlOutputV051 # :nodoc:
3
+ include LibXML
4
+
5
+ @@eeml_version = Constants::EEML['0.5.1']
6
+ # main method. creates an EEML 0.5.1 document for the given environment.
7
+ def to_eeml(environment)
8
+ doc = XML::Document.new
9
+ eeml = doc.root = XML::Node.new('eeml')
10
+ XML::Namespace.new(eeml, nil, @@eeml_version[:href])
11
+ XML::Namespace.new(eeml, 'xsi', Constants::XSI_NAMESPACE)
12
+ eeml['version'] = @@eeml_version[:version]
13
+ eeml['xsi:schemaLocation'] = @@eeml_version[:schema_location]
14
+ eeml << xml_node_for_environment(environment)
15
+ return doc.to_s(:encoding => XML::Encoding::UTF_8)
16
+ end
17
+
18
+ def xml_node_for_environment(environment)
19
+ environment_node = XML::Node.new('environment')
20
+
21
+ #TODO: write all these strings out safely for xml
22
+
23
+ environment_node['updated'] = environment.updated.utc.iso8601 unless environment.updated.nil?
24
+ environment_node['id'] = environment.identifier.to_s unless environment.identifier.blank?
25
+ environment_node['creator'] = environment.creator.to_s unless environment.creator.blank?
26
+
27
+ unless environment.title.blank?
28
+ environment_node << title_node = XML::Node.new('title')
29
+ title_node << environment.title
30
+ end
31
+
32
+ unless environment.feed_url.blank?
33
+ environment_node << feed_node = XML::Node.new('feed')
34
+ feed_node << environment.feed_url
35
+ end
36
+
37
+ unless environment.status.blank?
38
+ environment_node << status_node = XML::Node.new('status')
39
+ status_node << environment.status
40
+ end
41
+
42
+ unless environment.description.blank?
43
+ environment_node << description_node = XML::Node.new('description')
44
+ description_node << environment.description
45
+ end
46
+
47
+ unless environment.icon.blank?
48
+ environment_node << icon_node = XML::Node.new('icon')
49
+ icon_node << environment.icon
50
+ end
51
+
52
+ unless environment.website.blank?
53
+ environment_node << website_node = XML::Node.new('website')
54
+ website_node << environment.website
55
+ end
56
+
57
+ unless environment.email.blank?
58
+ environment_node << email_node = XML::Node.new('email')
59
+ email_node << environment.email
60
+ end
61
+
62
+ unless environment.location.nil?
63
+ environment_node << location_node = XML::Node.new('location')
64
+ location_node['domain'] = environment.location.domain
65
+ location_node['exposure'] = environment.location.exposure unless environment.location.exposure.blank?
66
+ location_node['disposition'] = environment.location.disposition unless environment.location.disposition.blank?
67
+
68
+ unless environment.location.name.blank?
69
+ location_node << location_name_node = XML::Node.new('name')
70
+ location_name_node << environment.location.name
71
+ end
72
+
73
+ location_node << lat_node = XML::Node.new('lat')
74
+ lat_node << environment.location.latitude
75
+
76
+ location_node << lng_node = XML::Node.new('lon')
77
+ lng_node << environment.location.longitude
78
+
79
+ unless environment.location.elevation.blank?
80
+ location_node << elevation_node = XML::Node.new('ele')
81
+ elevation_node << environment.location.elevation
82
+ end
83
+ end
84
+
85
+ environment.datastreams.each do |datastream|
86
+ environment_node << datastream_to_xml_node(datastream)
87
+ end
88
+
89
+ return environment_node
90
+ end
91
+
92
+ def datastream_to_xml_node(datastream)
93
+ datastream_node = XML::Node.new('data')
94
+ datastream_node['id'] = datastream.identifier.to_s
95
+
96
+ datastream.tags.each do |tag|
97
+ tag_node = XML::Node.new('tag')
98
+ tag_node << tag
99
+ datastream_node << tag_node
100
+ end
101
+
102
+ datastream_node << value_node = XML::Node.new('current_value')
103
+ datastream_node << max_value_node = XML::Node.new('max_value', datastream.max_value.to_s) unless datastream.max_value.to_s.empty?
104
+ datastream_node << min_value_node = XML::Node.new('min_value', datastream.min_value.to_s) unless datastream.min_value.to_s.empty?
105
+
106
+ value_node << datastream.value.to_s
107
+
108
+ unless datastream.unit_value.to_s.empty? && datastream.unit_type.to_s.empty? && datastream.unit_symbol.to_s.empty?
109
+ datastream_node << unit_node = XML::Node.new('unit')
110
+ unit_node['type'] = datastream.unit_type.to_s unless datastream.unit_type.to_s.empty?
111
+ unit_node['symbol'] = datastream.unit_symbol.to_s unless datastream.unit_symbol.to_s.empty?
112
+ unit_node << datastream.unit_value.to_s unless datastream.unit_value.to_s.empty?
113
+ end
114
+
115
+ return datastream_node
116
+ end
117
+ end
118
+ end
@@ -5,6 +5,7 @@ module Eeml
5
5
  include LibXML
6
6
  include Exceptions
7
7
 
8
+ @@eeml_version = Constants::EEML['0.5.0']
8
9
  #main method
9
10
 
10
11
  #take an xml string, and create an Environment from it.
@@ -53,13 +54,13 @@ module Eeml
53
54
 
54
55
  #multiple (zero or more)
55
56
  def extract_environments_from_doc(doc)
56
- env_nodes = doc.find('x:environment', "x:#{Constants::EEML5_HREF}")
57
+ env_nodes = doc.find('x:environment', "x:#{@@eeml_version[:href]}")
57
58
  return env_nodes.map{|env_node| new_env = Environment.new; extract_environment_from_node(env_node, new_env)}
58
59
  end
59
60
 
60
61
  #single, mandatory
61
62
  def extract_environment_from_doc(doc, env_to_populate)
62
- env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{Constants::EEML5_HREF}")
63
+ env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{Constants::EEML['0.5.0'][:href]}")
63
64
  return extract_environment_from_node(env_node, env_to_populate)
64
65
  end
65
66
 
@@ -71,20 +72,20 @@ module Eeml
71
72
 
72
73
  env.creator = env_node['creator']
73
74
 
74
- env.title = optional_content(env_node, 'x:title', 'title', "x:#{Constants::EEML5_HREF}")
75
- env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{Constants::EEML5_HREF}")
76
- env.description = optional_content(env_node, 'x:description', 'description', "x:#{Constants::EEML5_HREF}")
77
- env.website = optional_content(env_node, 'x:website', 'website', "x:#{Constants::EEML5_HREF}")
78
- env.status = optional_content(env_node, 'x:status', 'status', "x:#{Constants::EEML5_HREF}")
79
- env.email = optional_content(env_node, 'x:email', 'email', "x:#{Constants::EEML5_HREF}")
80
- env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{Constants::EEML5_HREF}")
81
- env.private = optional_content(env_node, 'x:private', 'private', "x:#{Constants::EEML5_HREF}")
75
+ env.title = optional_content(env_node, 'x:title', 'title', "x:#{@@eeml_version[:href]}")
76
+ env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{@@eeml_version[:href]}")
77
+ env.description = optional_content(env_node, 'x:description', 'description', "x:#{@@eeml_version[:href]}")
78
+ env.website = optional_content(env_node, 'x:website', 'website', "x:#{@@eeml_version[:href]}")
79
+ env.status = optional_content(env_node, 'x:status', 'status', "x:#{@@eeml_version[:href]}")
80
+ env.email = optional_content(env_node, 'x:email', 'email', "x:#{@@eeml_version[:href]}")
81
+ env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{@@eeml_version[:href]}")
82
+ env.private = optional_content(env_node, 'x:private', 'private', "x:#{@@eeml_version[:href]}")
82
83
 
83
84
  #find_first_node_or_fail(env_node, 'x:location', 'location')
84
- loc_node = env_node.find_first('x:location', "x:#{Constants::EEML5_HREF}")
85
+ loc_node = env_node.find_first('x:location', "x:#{@@eeml_version[:href]}")
85
86
  env.location = extractLocation(loc_node) if loc_node
86
87
 
87
- datastream_nodes = env_node.find('x:data', "x:#{Constants::EEML5_HREF}")
88
+ datastream_nodes = env_node.find('x:data', "x:#{@@eeml_version[:href]}")
88
89
  # raise NoDataStreams.new, "no datastreams found" if datastream_nodes.empty?
89
90
  env.datastreams = extractDataStreams(datastream_nodes) unless datastream_nodes.empty?
90
91
 
@@ -102,10 +103,10 @@ module Eeml
102
103
  loc.domain = node['domain']
103
104
  loc.disposition = node['disposition']
104
105
  loc.exposure = node['exposure']
105
- loc.name = optional_content(node, 'x:name', 'name', "x:#{Constants::EEML5_HREF}")
106
- loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{Constants::EEML5_HREF}")
107
- loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{Constants::EEML5_HREF}")
108
- loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{Constants::EEML5_HREF}")
106
+ loc.name = optional_content(node, 'x:name', 'name', "x:#{@@eeml_version[:href]}")
107
+ loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{@@eeml_version[:href]}")
108
+ loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{@@eeml_version[:href]}")
109
+ loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{@@eeml_version[:href]}")
109
110
  return loc
110
111
  end
111
112
 
@@ -139,11 +140,11 @@ module Eeml
139
140
  data = DataStream.new
140
141
  raise MissingAttribute.new(node.name, 'id') if node['id'].nil?
141
142
  data.identifier = node['id']
142
- node.find('x:tag', "x:#{Constants::EEML5_HREF}").each do |tag_node|
143
+ node.find('x:tag', "x:#{@@eeml_version[:href]}").each do |tag_node|
143
144
  data.tags << tag_node.content.strip
144
145
  end
145
146
 
146
- value_nodes = node.find('x:value', "x:#{Constants::EEML5_HREF}")
147
+ value_nodes = node.find('x:value', "x:#{@@eeml_version[:href]}")
147
148
  raise exception_for_node(node, DataMissingValue, "Data node is missing value node.") if value_nodes.empty?
148
149
  raise exception_for_node(node, DataHasMultipleValues, "Data node has multiple 'value' nodes.") if value_nodes.size > 1
149
150
 
@@ -156,7 +157,7 @@ module Eeml
156
157
 
157
158
  data.add_value(value)
158
159
 
159
- unit_nodes = node.find('x:unit', "x:#{Constants::EEML5_HREF}")
160
+ unit_nodes = node.find('x:unit', "x:#{@@eeml_version[:href]}")
160
161
  raise exception_for_node(node, DataHasMultipleUnits, "Data node has multiple 'unit' nodes.") if unit_nodes.size > 1
161
162
 
162
163
  unit_node = unit_nodes.first
@@ -0,0 +1,211 @@
1
+ require "parsedate.rb"
2
+ module Eeml
3
+ #a parser for xml eeml v051, implemented with LibXML
4
+ class LibXMLEemlParserV051 # :nodoc:
5
+ include LibXML
6
+ include Exceptions
7
+
8
+ @@eeml_version = Constants::EEML['0.5.1']
9
+ #main method
10
+
11
+ #take an xml string, and create an Environment from it.
12
+ #If an optional environment is given, that will be populated (overwritten) instead of a new environment.
13
+ def make_environment_from_xml(xml_str, given_environment = nil)
14
+ doc = parse_xml(xml_str)
15
+ raise MissingNamespace if doc.root.namespaces.namespace.blank?
16
+ env = given_environment || Environment.new
17
+ #TODO: what has to be reset in a given environment before passing it for re-population?
18
+ return extract_environment_from_doc(doc, env)
19
+ end
20
+
21
+ #take an xml string containing zero or more environment nodes, and create an array of Environment objects from it.
22
+ def make_environments_from_xml(xml_str)
23
+ doc = parse_xml(xml_str)
24
+ raise MissingNamespace if doc.root.namespaces.namespace.blank?
25
+ return extract_environments_from_doc(doc)
26
+ end
27
+
28
+ protected
29
+
30
+ def parse_xml(xml_str)
31
+ errors = []
32
+ #http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/Error.html
33
+ #TODO: is the error handler set up per thread? (XML::Error.set_handler)
34
+ XML::Error.set_handler { |error| errors << error }
35
+
36
+ #TODO: performance - is this expensive?
37
+ #TODO: are these configurations per-thread? If they're global (e.g. class variables) then we shouldn't be setting them here.
38
+ XML.default_line_numbers=true
39
+
40
+ parser = XML::Parser.string(xml_str)
41
+ begin
42
+ doc = parser.parse
43
+ rescue XML::Error => e
44
+ #note: errors var available here, too.
45
+ raise BadXML, "Malformed xml: #{e.class}: #{e}", e.backtrace
46
+ end
47
+ #validation?
48
+ # seems we have to recreate our XML::Schema object on each invocation
49
+ # else libxml segfaults very quickly
50
+ #doc.validate_schema(XML::Schema.from_string(IO.read(LOCAL_EEML5_SCHEMA_LOCATION)))
51
+ return doc
52
+ end
53
+
54
+
55
+ #multiple (zero or more)
56
+ def extract_environments_from_doc(doc)
57
+ env_nodes = doc.find('x:environment', "x:#{@@eeml_version[:href]}")
58
+ return env_nodes.map{|env_node| new_env = Environment.new; extract_environment_from_node(env_node, new_env)}
59
+ end
60
+
61
+ #single, mandatory
62
+ def extract_environment_from_doc(doc, env_to_populate)
63
+ env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{@@eeml_version[:href]}")
64
+ return extract_environment_from_node(env_node, env_to_populate)
65
+ end
66
+
67
+ #single, from node (everyone uses this to get the work done)
68
+ def extract_environment_from_node(env_node, env_to_populate)
69
+ env = env_to_populate
70
+ env.identifier = env_node['id']
71
+ env.updated = Time.gm(*ParseDate.parsedate(env_node['updated'])).utc if !env_node['updated'].nil?
72
+
73
+ env.creator = env_node['creator']
74
+
75
+ env.title = optional_content(env_node, 'x:title', 'title', "x:#{@@eeml_version[:href]}")
76
+ env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{@@eeml_version[:href]}")
77
+ env.description = optional_content(env_node, 'x:description', 'description', "x:#{@@eeml_version[:href]}")
78
+ env.website = optional_content(env_node, 'x:website', 'website', "x:#{@@eeml_version[:href]}")
79
+ env.status = optional_content(env_node, 'x:status', 'status', "x:#{@@eeml_version[:href]}")
80
+ env.email = optional_content(env_node, 'x:email', 'email', "x:#{@@eeml_version[:href]}")
81
+ env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{@@eeml_version[:href]}")
82
+ env.private = optional_content(env_node, 'x:private', 'private', "x:#{@@eeml_version[:href]}")
83
+
84
+ #find_first_node_or_fail(env_node, 'x:location', 'location')
85
+ loc_node = env_node.find_first('x:location', "x:#{@@eeml_version[:href]}")
86
+ env.location = extractLocation(loc_node) if loc_node
87
+
88
+ datastream_nodes = env_node.find('x:data', "x:#{@@eeml_version[:href]}")
89
+ # raise NoDataStreams.new, "no datastreams found" if datastream_nodes.empty?
90
+ env.datastreams = extractDataStreams(datastream_nodes) unless datastream_nodes.empty?
91
+
92
+ return env
93
+ end
94
+
95
+ def extractLocation(node)
96
+ #<location domain="physical" exposure="outdoor" disposition="mobile">
97
+ # <lat>50.1</lat>
98
+ # <lon>48.7</lon>
99
+ # <ele>1.34</ele>
100
+ #</location>
101
+ raise "given nil node" if node.nil?
102
+ loc = Location.new
103
+ loc.domain = node['domain']
104
+ loc.disposition = node['disposition']
105
+ loc.exposure = node['exposure']
106
+ loc.name = optional_content(node, 'x:name', 'name', "x:#{@@eeml_version[:href]}")
107
+ loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{@@eeml_version[:href]}")
108
+ loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{@@eeml_version[:href]}")
109
+ loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{@@eeml_version[:href]}")
110
+ return loc
111
+ end
112
+
113
+ #return an array (TODO: or a hash?) of DataStream objects from the given list of data nodes
114
+ def extractDataStreams(nodes)
115
+ #<data id="blah1">...</data><data id="blah2">...</data>
116
+ dataStreams = []
117
+ nodes.each do |node|
118
+ dataStreams << extractDataStream(node)
119
+ end
120
+ return dataStreams
121
+ end
122
+
123
+ #builds and returns a detailed exception of the given class, for problems concerning the given node (or its missing children)
124
+ #details include node's name and line number (zero if not available)
125
+ def exception_for_node(node, exception_class, message)
126
+ ex = exception_class.new(message)
127
+ ex.line_num = node.line_num
128
+ ex.node_name = node_name_or_root(node)
129
+ return ex
130
+ end
131
+
132
+
133
+ def extractDataStream(node)
134
+ #<data id="0">
135
+ #<tag>some_tag</tag>
136
+ #<tag>another_tag</tag>
137
+ #<current_value>0</current_value>
138
+ #<min_value>0.0</min_value>
139
+ #<max_value>1022.0</max_value>
140
+ #<unit symbol="C" type="basicSI">Celsius</unit>
141
+ #</data>
142
+ data = DataStream.new
143
+ raise MissingAttribute.new(node.name, 'id') if node['id'].nil?
144
+ data.identifier = node['id']
145
+ node.find('x:tag', "x:#{@@eeml_version[:href]}").each do |tag_node|
146
+ data.tags << tag_node.content.strip
147
+ end
148
+
149
+ value_nodes = node.find('x:current_value', "x:#{@@eeml_version[:href]}")
150
+ raise exception_for_node(node, DataMissingValue, "Data node is missing value node.") if value_nodes.empty?
151
+ raise exception_for_node(node, DataHasMultipleValues, "Data node has multiple 'value' nodes.") if value_nodes.size > 1
152
+
153
+ value_node = value_nodes.first
154
+
155
+ max_value_node = node.find_first('x:max_value', "x:#{@@eeml_version[:href]}")
156
+ min_value_node = node.find_first('x:min_value', "x:#{@@eeml_version[:href]}")
157
+
158
+ value = Value.new
159
+ value.min_value = min_value_node.content if min_value_node
160
+ value.max_value = max_value_node.content if max_value_node
161
+ value.value = value_node.content.strip
162
+
163
+ data.add_value(value)
164
+
165
+ unit_nodes = node.find('x:unit', "x:#{@@eeml_version[:href]}")
166
+ raise exception_for_node(node, DataHasMultipleUnits, "Data node has multiple 'unit' nodes.") if unit_nodes.size > 1
167
+
168
+ unit_node = unit_nodes.first
169
+ unless unit_node.nil?
170
+ data.unit_symbol = unit_node['symbol']
171
+ data.unit_type = unit_node['type']
172
+ data.unit_value = unit_node.content.strip
173
+ end
174
+
175
+ return data
176
+ end
177
+
178
+ #Helpers ------------------------------------------------------------------
179
+ #Consider mixing these in to the libxml parser for more readable code
180
+
181
+ #raises MissingNode if the node isn't there
182
+ def mandatory_content(base_node, xpath, description, nslist = nil)
183
+ node = base_node.find_first(xpath, nslist)
184
+ raise(MissingNode.new(node_name_or_root(base_node), description, xpath)) if node.nil?
185
+ return node.content
186
+ end
187
+
188
+ #returns the node's content, or the given default if the node isn't there (default itself defaults to nil)
189
+ #description isn't used, but keeps our signature same as mandatory_content(), up to that point.
190
+ def optional_content(base_node, xpath, description, nslist = nil, default = nil)
191
+ node = base_node.find_first(xpath, nslist)
192
+ return node.nil? ? default : node.content
193
+ end
194
+
195
+
196
+ #get the name of the given node if it is a node, or 'root' if it is a doc.
197
+ #for use only for error messages
198
+ def node_name_or_root(node)
199
+ node.respond_to?(:name) ? node.name : 'root'
200
+ end
201
+
202
+ def find_first_node_or_fail(base_node, xpath, description, nslist = nil)
203
+ node = base_node.find_first(xpath, nslist)
204
+ raise(MissingNode.new(node_name_or_root(base_node), description, xpath)) if node.nil?
205
+ return node
206
+ end
207
+
208
+ end
209
+
210
+ end
211
+
@@ -1,14 +1,16 @@
1
1
  require 'eeml/libxml_eeml_output_v005'
2
+ require 'eeml/libxml_eeml_output_v051'
2
3
  require 'eeml/json_output'
3
4
 
4
5
  module Eeml
5
6
  class OutputRegistry # :nodoc:
6
7
  #look at the given xml, build and return a new v005 or 006 parser, accordingly
7
- def self.get_xml_output_for(version = Constants::EEML5_VERSION)
8
+ def self.get_xml_output_for(version = Constants::EEML['0.5.0'][:version])
9
+ return LibXMLEemlOutputV051.new if version == Constants::EEML['0.5.1'][:version]
8
10
  LibXMLEemlOutputV005.new
9
11
  end
10
12
 
11
- def self.get_json_output_for(version = Constants::EEML5_VERSION)
13
+ def self.get_json_output_for(version = Constants::EEML['0.5.0'][:version])
12
14
  JsonOutput.new
13
15
  end
14
16
 
data/lib/eeml.rb CHANGED
@@ -15,7 +15,7 @@ require 'time'
15
15
  module Eeml
16
16
 
17
17
  # library version number
18
- VERSION = '0.0.17'
18
+ VERSION = '0.0.18'
19
19
 
20
20
  # TODO: put in some configuration file, not here
21
21
  LOCAL_EEML_SCHEMA_LOCATION = 'schemas/eeml/005.xsd'
@@ -1,15 +1,21 @@
1
1
  {"datastreams":[
2
- {"tags":["tagD0"],
3
- "values":[{"value":"0","at":"2009-02-11T10:56:56Z"}],
4
- "min_value":"-9999.0",
5
- "max_value":"1022.0",
6
- "unit":{"type":"basicSI","label":"Celsius","symbol":"C"},
7
- "id":"0"},
8
- {"values":[{"value":"33","at":"2009-02-11T10:56:55Z"}],
2
+ {
3
+ "tags":["tagD0"],
4
+ "current_value":"0",
5
+ "at":"2009-02-11T10:56:56Z",
6
+ "min_value":"-9999.0",
7
+ "max_value":"1022.0",
8
+ "unit":{"type":"basicSI","label":"Celsius","symbol":"C"},
9
+ "id":"0"
10
+ },
11
+ {
12
+ "current_value":"33",
13
+ "at":"2009-02-11T10:56:55Z",
9
14
  "min_value":"0.0","max_value":"1023.0",
10
15
  "id":"1"},
11
16
  {"tags":["tagD2a","tagD2b","tagD2c"],
12
- "values":[{"value":"42.1","at":"2009-02-11T10:55:10Z"}],
17
+ "current_value":"42.1",
18
+ "at":"2009-02-11T10:55:10Z",
13
19
  "min_value":"23.4","max_value":"1021.0",
14
20
  "id":"2"}
15
21
  ],
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
3
+ <environment>
4
+ <data id="0">
5
+ <tag>sometag</tag>
6
+ <current_value>65</current_value>
7
+ <max_value>100.0</max_value>
8
+ <min_value>4.0</min_value>
9
+ </data>
10
+ </environment>
11
+ </eeml>
@@ -566,6 +566,16 @@ class TestEnvironment < Test::Unit::TestCase
566
566
  assert_equal expected_xml, xml_output
567
567
  end
568
568
 
569
+ test "should output to eeml 0.5.1 ok" do
570
+ env = create_env_from_xml_file('eeml_datastream_051.xml')
571
+ xml_output = env.to_eeml('0.5.1')
572
+ assert_not_nil xml_output
573
+
574
+ expected_xml = File.read('test/data/eeml_datastream_051.xml')
575
+ assert_equal expected_xml, xml_output
576
+
577
+ end
578
+
569
579
  implement "output - check that 'feed' url is correctly assembled" do
570
580
  end
571
581
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eeml
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 59
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 17
9
- version: 0.0.17
9
+ - 18
10
+ version: 0.0.18
10
11
  platform: ruby
11
12
  authors:
12
13
  - Neill Bogie
@@ -16,16 +17,18 @@ autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2010-07-02 00:00:00 +01:00
20
+ date: 2010-07-20 00:00:00 +01:00
20
21
  default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
23
24
  name: libxml-ruby
24
25
  prerelease: false
25
26
  requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
26
28
  requirements:
27
29
  - - ">="
28
30
  - !ruby/object:Gem::Version
31
+ hash: 21
29
32
  segments:
30
33
  - 1
31
34
  - 1
@@ -37,9 +40,11 @@ dependencies:
37
40
  name: json
38
41
  prerelease: false
39
42
  requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
40
44
  requirements:
41
45
  - - ">="
42
46
  - !ruby/object:Gem::Version
47
+ hash: 1
43
48
  segments:
44
49
  - 1
45
50
  - 4
@@ -76,7 +81,9 @@ files:
76
81
  - lib/eeml/json_environment_parser_v100.rb
77
82
  - lib/eeml/json_output.rb
78
83
  - lib/eeml/libxml_eeml_output_v005.rb
84
+ - lib/eeml/libxml_eeml_output_v051.rb
79
85
  - lib/eeml/libxml_eeml_parser_v005.rb
86
+ - lib/eeml/libxml_eeml_parser_v051.rb
80
87
  - lib/eeml/output_registry.rb
81
88
  - schemas/eeml/005.xsd
82
89
  - test/data/.gitignore
@@ -91,6 +98,7 @@ files:
91
98
  - test/data/doc_1_v6_private.json
92
99
  - test/data/doc_2.xml
93
100
  - test/data/doc_2_expected.json
101
+ - test/data/eeml_datastream_051.xml
94
102
  - test/data/list.xml
95
103
  - test/data/minimal.xml
96
104
  - test/data/no_namespace.xml
@@ -110,23 +118,27 @@ rdoc_options:
110
118
  require_paths:
111
119
  - lib
112
120
  required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
113
122
  requirements:
114
123
  - - ">="
115
124
  - !ruby/object:Gem::Version
125
+ hash: 3
116
126
  segments:
117
127
  - 0
118
128
  version: "0"
119
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
120
131
  requirements:
121
132
  - - ">="
122
133
  - !ruby/object:Gem::Version
134
+ hash: 3
123
135
  segments:
124
136
  - 0
125
137
  version: "0"
126
138
  requirements: []
127
139
 
128
140
  rubyforge_project:
129
- rubygems_version: 1.3.6
141
+ rubygems_version: 1.3.7
130
142
  signing_key:
131
143
  specification_version: 3
132
144
  summary: Simple little library for programmatically manipulating EEML documents.