eeml 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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.