eeml 0.0.7 → 0.0.8
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/Manifest +3 -1
- data/eeml.gemspec +4 -4
- data/lib/eeml/constants.rb +6 -10
- data/lib/eeml/environment.rb +65 -13
- data/lib/eeml/environment_builder.rb +30 -0
- data/lib/eeml/json_environment_parser_v005.rb +14 -7
- data/lib/eeml/json_environment_parser_v006.rb +81 -0
- data/lib/eeml/json_output.rb +2 -2
- data/lib/eeml/libxml_eeml_output_v005.rb +4 -4
- data/lib/eeml/libxml_eeml_parser_v005.rb +27 -24
- data/lib/eeml/output_registry.rb +2 -2
- data/lib/eeml.rb +3 -2
- data/test/data/doc_1_v6.json +30 -0
- data/test/test_environment.rb +70 -8
- data.tar.gz.sig +0 -0
- metadata +7 -4
- metadata.gz.sig +0 -0
- data/lib/eeml/parser_registry.rb +0 -18
data/Manifest
CHANGED
@@ -9,18 +9,20 @@ lib/eeml.rb
|
|
9
9
|
lib/eeml/constants.rb
|
10
10
|
lib/eeml/csv_parser.rb
|
11
11
|
lib/eeml/environment.rb
|
12
|
+
lib/eeml/environment_builder.rb
|
12
13
|
lib/eeml/exceptions.rb
|
13
14
|
lib/eeml/json_environment_parser_v005.rb
|
15
|
+
lib/eeml/json_environment_parser_v006.rb
|
14
16
|
lib/eeml/json_output.rb
|
15
17
|
lib/eeml/libxml_eeml_output_v005.rb
|
16
18
|
lib/eeml/libxml_eeml_parser_v005.rb
|
17
19
|
lib/eeml/output_registry.rb
|
18
|
-
lib/eeml/parser_registry.rb
|
19
20
|
schemas/eeml/005.xsd
|
20
21
|
test/data/complete_namespaced.xml
|
21
22
|
test/data/difficult_tag.xml
|
22
23
|
test/data/doc_1.json
|
23
24
|
test/data/doc_1.xml
|
25
|
+
test/data/doc_1_v6.json
|
24
26
|
test/data/doc_2.xml
|
25
27
|
test/data/doc_2_expected.json
|
26
28
|
test/data/list.xml
|
data/eeml.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{eeml}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.8"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Neill Bogie, Sam Mulube"]
|
9
9
|
s.cert_chain = ["/home/sam/.gem/gem-public_cert.pem"]
|
10
|
-
s.date = %q{2009-
|
10
|
+
s.date = %q{2009-11-21}
|
11
11
|
s.description = %q{Simple little library for programmatically manipulating EEML documents, in particular this library is designed to work with the Pachube web service.}
|
12
12
|
s.email = %q{sam.mulube@gmail.com}
|
13
|
-
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/blank.rb", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/eeml/exceptions.rb", "lib/eeml/json_environment_parser_v005.rb", "lib/eeml/
|
14
|
-
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "example.rb", "lib/blank.rb", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/eeml/exceptions.rb", "lib/eeml/json_environment_parser_v005.rb", "lib/eeml/
|
13
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/blank.rb", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/eeml/environment_builder.rb", "lib/eeml/exceptions.rb", "lib/eeml/json_environment_parser_v005.rb", "lib/eeml/json_environment_parser_v006.rb", "lib/eeml/json_output.rb", "lib/eeml/libxml_eeml_output_v005.rb", "lib/eeml/libxml_eeml_parser_v005.rb", "lib/eeml/output_registry.rb"]
|
14
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "example.rb", "lib/blank.rb", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/eeml/environment_builder.rb", "lib/eeml/exceptions.rb", "lib/eeml/json_environment_parser_v005.rb", "lib/eeml/json_environment_parser_v006.rb", "lib/eeml/json_output.rb", "lib/eeml/libxml_eeml_output_v005.rb", "lib/eeml/libxml_eeml_parser_v005.rb", "lib/eeml/output_registry.rb", "schemas/eeml/005.xsd", "test/data/complete_namespaced.xml", "test/data/difficult_tag.xml", "test/data/doc_1.json", "test/data/doc_1.xml", "test/data/doc_1_v6.json", "test/data/doc_2.xml", "test/data/doc_2_expected.json", "test/data/list.xml", "test/data/minimal.xml", "test/data/no_namespace.xml", "test/data/out_empty.xml", "test/libxml_test_helper.rb", "test/test_environment.rb", "test/test_helper.rb", "test/test_libxml_eeml_parser_v005.rb", "test/test_libxml_test_helper.rb", "eeml.gemspec"]
|
15
15
|
s.homepage = %q{}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Eeml", "--main", "README"]
|
17
17
|
s.require_paths = ["lib"]
|
data/lib/eeml/constants.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
module Eeml
|
2
2
|
module Constants
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
8
|
+
EEML5_NAMESPACE = ":#{EEML5_HREF}"
|
9
9
|
XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
|
10
10
|
|
11
|
-
|
12
|
-
# TODO: better encapsulated as a set of methods.
|
13
|
-
#++
|
14
|
-
XML_TIME_FORMAT_STRING = "%Y-%m-%dT%H:%M:%SZ"
|
15
|
-
|
11
|
+
EEML6_VERSION = "0.6"
|
16
12
|
end
|
17
13
|
end
|
18
14
|
|
data/lib/eeml/environment.rb
CHANGED
@@ -20,23 +20,76 @@ module Eeml
|
|
20
20
|
# One of the component classes of Environment. Represents an individual datastream, and provides access to it's value
|
21
21
|
# and other attributes. Environments can have zero or more datastreams.
|
22
22
|
class DataStream
|
23
|
-
attr_accessor :identifier, :
|
23
|
+
attr_accessor :identifier, :tags, :unit_symbol, :unit_type, :unit_value
|
24
|
+
attr_accessor :values
|
24
25
|
|
25
26
|
def initialize(options = {})
|
26
27
|
@identifier = options[:identifier]
|
27
|
-
@value = options[:value]
|
28
|
-
@max_value = options[:max_value]
|
29
|
-
@min_value = options[:min_value]
|
30
28
|
@tags = []
|
31
29
|
@unit_symbol = options[:unit_symbol]
|
32
30
|
@unit_type = options[:unit_type]
|
33
31
|
@unit_value = options[:unit_value]
|
32
|
+
@values = []
|
33
|
+
@values << Value.new(:value => options[:value],
|
34
|
+
:max_value => options[:max_value],
|
35
|
+
:min_value => options[:min_value],
|
36
|
+
:recorded_at => options[:recorded_at])
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_value(value)
|
40
|
+
@values << value
|
41
|
+
end
|
42
|
+
|
43
|
+
def remove_last_value
|
44
|
+
@values.pop
|
45
|
+
end
|
46
|
+
|
47
|
+
def min_value
|
48
|
+
unless @values.last.nil?
|
49
|
+
return @values.last.min_value
|
50
|
+
else
|
51
|
+
return nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def max_value
|
56
|
+
unless @values.last.nil?
|
57
|
+
return @values.last.max_value
|
58
|
+
else
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def value
|
64
|
+
unless @values.last.nil?
|
65
|
+
return @values.last.value
|
66
|
+
else
|
67
|
+
return nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def recorded_at
|
72
|
+
unless @values.last.nil?
|
73
|
+
return @values.last.recorded_at
|
74
|
+
else
|
75
|
+
return nil
|
76
|
+
end
|
34
77
|
end
|
35
78
|
|
36
79
|
def to_s
|
37
80
|
"identifier: '#{@identifier}', value: '#{@value}', min_value: '#{@min_value}', max_value: '#{@max_value}', tags: '#{@tags.join(", ")}'"
|
38
81
|
end
|
82
|
+
end
|
39
83
|
|
84
|
+
class Value
|
85
|
+
attr_accessor :min_value, :max_value, :value, :recorded_at
|
86
|
+
|
87
|
+
def initialize(options = {})
|
88
|
+
@min_value = options[:min_value]
|
89
|
+
@max_value = options[:max_value]
|
90
|
+
@value = options[:value]
|
91
|
+
@recorded_at = options[:recorded_at]
|
92
|
+
end
|
40
93
|
end
|
41
94
|
|
42
95
|
# This class represents the main point of entry to this library. In general we will be creating instances of this class, either
|
@@ -73,20 +126,17 @@ module Eeml
|
|
73
126
|
|
74
127
|
# Create multiple Environment objects from an EEML string containing multiple `environment` stanzas.
|
75
128
|
def self.new_list_from_eeml(xml_str)
|
76
|
-
|
77
|
-
return parser.make_environments_from_xml(xml_str)
|
129
|
+
return EnvironmentBuilder.build_list_from_xml(xml_str)
|
78
130
|
end
|
79
131
|
|
80
132
|
# Create a new Environment object from an EEML string.
|
81
133
|
def self.new_from_eeml(xml_str)
|
82
|
-
|
83
|
-
return parser.make_environment_from_xml(xml_str)
|
134
|
+
return EnvironmentBuilder.build_from_xml(xml_str)
|
84
135
|
end
|
85
136
|
|
86
137
|
# Create a new Environment object from a JSON string.
|
87
138
|
def self.new_from_json(json_str)
|
88
|
-
|
89
|
-
return parser.make_environment_from_json(json_str)
|
139
|
+
return EnvironmentBuilder.build_from_json(json_str)
|
90
140
|
end
|
91
141
|
|
92
142
|
def update_datastreams_from_csv_values!(csv_values)
|
@@ -95,10 +145,12 @@ module Eeml
|
|
95
145
|
datastream = datastreams[index]
|
96
146
|
#if we don't have an existing datastream at same index, create new one
|
97
147
|
if datastream.nil?
|
98
|
-
|
148
|
+
datastream = DataStream.new(:identifier => index, :ordering => index)
|
149
|
+
datastream.add_value(Value.new(:value => new_val))
|
150
|
+
self.datastreams << datastream
|
99
151
|
else
|
100
152
|
#we had a match, so update the existing datastream
|
101
|
-
datastream.value = new_val
|
153
|
+
datastream.values.last.value = new_val
|
102
154
|
end
|
103
155
|
end
|
104
156
|
|
@@ -110,7 +162,7 @@ module Eeml
|
|
110
162
|
end
|
111
163
|
end
|
112
164
|
|
113
|
-
def to_eeml(version = Constants::
|
165
|
+
def to_eeml(version = Constants::EEML5_VERSION)
|
114
166
|
outputter = OutputRegistry.get_xml_output_for(version)
|
115
167
|
outputter.to_eeml(self)
|
116
168
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'eeml/libxml_eeml_parser_v005'
|
2
|
+
require 'eeml/json_environment_parser_v005'
|
3
|
+
require 'eeml/json_environment_parser_v006'
|
4
|
+
|
5
|
+
module Eeml
|
6
|
+
class EnvironmentBuilder # :nodoc:
|
7
|
+
def self.build_from_xml(xml_str)
|
8
|
+
parser = LibXMLEemlParserV005.new
|
9
|
+
return parser.make_environment_from_xml(xml_str)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.build_list_from_xml(xml_str)
|
13
|
+
parser = LibXMLEemlParserV005.new
|
14
|
+
return parser.make_environments_from_xml(xml_str)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.build_from_json(json_str)
|
18
|
+
json = JSON.parse(json_str)
|
19
|
+
if json["version"] == EEML5_VERSION
|
20
|
+
parser = JsonEnvironmentParserV005.new
|
21
|
+
elsif json["version"] == EEML6_VERSION
|
22
|
+
parser = JsonEnvironmentParserV006.new
|
23
|
+
else
|
24
|
+
raise "Invalid version specification. Permitted versions are #{EEML5_VERSION} and #{EEML6_VERSION}"
|
25
|
+
end
|
26
|
+
return parser.make_environment_from_hash(json)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -3,8 +3,7 @@ module Eeml
|
|
3
3
|
class JsonEnvironmentParserV005 # :nodoc:
|
4
4
|
include Exceptions
|
5
5
|
|
6
|
-
def
|
7
|
-
env_hash = JSON.parse(json_str)
|
6
|
+
def make_environment_from_hash(env_hash)
|
8
7
|
env = Environment.new(:title => env_hash["title"],
|
9
8
|
:description => env_hash["description"],
|
10
9
|
:feed_url => env_hash["feed"],
|
@@ -14,7 +13,7 @@ module Eeml
|
|
14
13
|
:status => env_hash["status"],
|
15
14
|
:identifier => env_hash["id"])
|
16
15
|
|
17
|
-
env.updated = Time.
|
16
|
+
env.updated = Time.gm(*ParseDate.parsedate(env_hash['updated'])) unless env_hash['updated'].nil?
|
18
17
|
|
19
18
|
env.location = buildLocation(env_hash)
|
20
19
|
|
@@ -23,6 +22,11 @@ module Eeml
|
|
23
22
|
return env
|
24
23
|
end
|
25
24
|
|
25
|
+
def make_environment_from_json(json_str)
|
26
|
+
env_hash = JSON.parse(json_str)
|
27
|
+
return make_environment_from_hash(env_hash)
|
28
|
+
end
|
29
|
+
|
26
30
|
private
|
27
31
|
|
28
32
|
def buildLocation(env_hash)
|
@@ -49,10 +53,13 @@ module Eeml
|
|
49
53
|
|
50
54
|
value_hash = datastream_hash["value"]
|
51
55
|
raise DataMissingValue if value_hash.nil?
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
#raise DataHasMultipleValues if value_hash.size > 1
|
57
|
+
|
58
|
+
value = Value.new(:value => value_hash["current_value"],
|
59
|
+
:min_value => value_hash["min_value"],
|
60
|
+
:max_value => value_hash["max_value"])
|
61
|
+
|
62
|
+
datastream.add_value(value)
|
56
63
|
|
57
64
|
unit_hash = datastream_hash["unit"]
|
58
65
|
unless unit_hash.nil?
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Eeml
|
2
|
+
# A parser for json environments based on the EEML 5 specification.
|
3
|
+
class JsonEnvironmentParserV006 # :nodoc:
|
4
|
+
include Exceptions
|
5
|
+
|
6
|
+
def make_environment_from_hash(env_hash)
|
7
|
+
env = Environment.new(:title => env_hash["title"],
|
8
|
+
:description => env_hash["description"],
|
9
|
+
:feed_url => env_hash["feed"],
|
10
|
+
:website => env_hash["website"],
|
11
|
+
:email => env_hash["email"],
|
12
|
+
:icon => env_hash["icon"],
|
13
|
+
:status => env_hash["status"],
|
14
|
+
:identifier => env_hash["id"])
|
15
|
+
|
16
|
+
env.updated = Time.gm(*ParseDate.parsedate(env_hash['updated'])) unless env_hash['updated'].nil?
|
17
|
+
|
18
|
+
env.location = buildLocation(env_hash)
|
19
|
+
|
20
|
+
env.datastreams = buildDatastreams(env_hash)
|
21
|
+
|
22
|
+
return env
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_environment_from_json(json_str)
|
26
|
+
env_hash = JSON.parse(json_str)
|
27
|
+
return make_environment_from_hash(env_hash)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def buildLocation(env_hash)
|
33
|
+
location_hash = env_hash["location"]
|
34
|
+
return if location_hash.nil?
|
35
|
+
Location.new(:name => location_hash["name"],
|
36
|
+
:latitude => location_hash["lat"],
|
37
|
+
:longitude => location_hash["lon"],
|
38
|
+
:elevation => location_hash["ele"],
|
39
|
+
:domain => location_hash["domain"],
|
40
|
+
:disposition => location_hash["disposition"],
|
41
|
+
:exposure => location_hash["exposure"])
|
42
|
+
end
|
43
|
+
|
44
|
+
def buildDatastreams(env_hash)
|
45
|
+
datastreams_hash = env_hash["datastreams"]
|
46
|
+
return if datastreams_hash.nil?
|
47
|
+
datastreams = []
|
48
|
+
datastreams_hash.each do |datastream_hash|
|
49
|
+
datastream = DataStream.new
|
50
|
+
raise MissingAttribute.new('id', "data") if datastream_hash['id'].nil?
|
51
|
+
datastream.identifier = datastream_hash['id']
|
52
|
+
datastream.tags = datastream_hash['tags'] unless datastream_hash['tags'].nil?
|
53
|
+
|
54
|
+
values_arr = datastream_hash["values"]
|
55
|
+
|
56
|
+
raise DataMissingValue if values_arr.nil?
|
57
|
+
|
58
|
+
values_arr.each do |v|
|
59
|
+
value = Value.new(:value => v["value"],
|
60
|
+
:min_value => v["min_value"],
|
61
|
+
:max_value => v["max_value"],
|
62
|
+
:recorded_at => v["recorded_at"])
|
63
|
+
|
64
|
+
datastream.add_value(value)
|
65
|
+
end
|
66
|
+
|
67
|
+
unit_hash = datastream_hash["unit"]
|
68
|
+
unless unit_hash.nil?
|
69
|
+
datastream.unit_symbol = unit_hash["symbol"]
|
70
|
+
datastream.unit_type = unit_hash["type"]
|
71
|
+
datastream.unit_value = unit_hash["label"]
|
72
|
+
end
|
73
|
+
|
74
|
+
datastreams << datastream
|
75
|
+
end
|
76
|
+
return datastreams
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
data/lib/eeml/json_output.rb
CHANGED
@@ -16,9 +16,9 @@ module Eeml
|
|
16
16
|
:website => environment.website,
|
17
17
|
:email => environment.email,
|
18
18
|
:icon => environment.icon,
|
19
|
-
:version =>
|
19
|
+
:version => EEML5_VERSION}
|
20
20
|
|
21
|
-
environment_hash[:updated] = environment.updated.
|
21
|
+
environment_hash[:updated] = environment.updated.utc.iso8601 unless environment.updated.nil? #TODO: was retrieved_at
|
22
22
|
|
23
23
|
environment_hash.delete_if { |key, value| value.blank? }
|
24
24
|
|
@@ -7,10 +7,10 @@ module Eeml
|
|
7
7
|
def to_eeml(environment)
|
8
8
|
doc = XML::Document.new
|
9
9
|
eeml = doc.root = XML::Node.new('eeml')
|
10
|
-
XML::Namespace.new(eeml, nil,
|
10
|
+
XML::Namespace.new(eeml, nil, EEML5_HREF)
|
11
11
|
XML::Namespace.new(eeml, 'xsi', XSI_NAMESPACE)
|
12
|
-
eeml['version'] =
|
13
|
-
eeml['xsi:schemaLocation'] =
|
12
|
+
eeml['version'] = EEML5_VERSION
|
13
|
+
eeml['xsi:schemaLocation'] = EEML5_SCHEMA_LOCATION
|
14
14
|
eeml << xml_node_for_environment(environment)
|
15
15
|
|
16
16
|
return doc.to_s(:encoding => XML::Encoding::UTF_8)
|
@@ -21,7 +21,7 @@ module Eeml
|
|
21
21
|
|
22
22
|
#TODO: write all these strings out safely for xml
|
23
23
|
|
24
|
-
environment_node['updated'] = environment.updated.
|
24
|
+
environment_node['updated'] = environment.updated.utc.iso8601 unless environment.updated.nil?
|
25
25
|
environment_node['id'] = environment.identifier.to_s unless environment.identifier.blank?
|
26
26
|
environment_node['creator'] = environment.creator.to_s unless environment.creator.blank?
|
27
27
|
|
@@ -46,20 +46,20 @@ module Eeml
|
|
46
46
|
#validation?
|
47
47
|
# seems we have to recreate our XML::Schema object on each invocation
|
48
48
|
# else libxml segfaults very quickly
|
49
|
-
#doc.validate_schema(XML::Schema.from_string(IO.read(
|
49
|
+
#doc.validate_schema(XML::Schema.from_string(IO.read(LOCAL_EEML5_SCHEMA_LOCATION)))
|
50
50
|
return doc
|
51
51
|
end
|
52
52
|
|
53
53
|
|
54
54
|
#multiple (zero or more)
|
55
55
|
def extract_environments_from_doc(doc)
|
56
|
-
env_nodes = doc.find('x:environment', "x:#{
|
56
|
+
env_nodes = doc.find('x:environment', "x:#{EEML5_HREF}")
|
57
57
|
return env_nodes.map{|env_node| new_env = Environment.new; extract_environment_from_node(env_node, new_env)}
|
58
58
|
end
|
59
59
|
|
60
60
|
#single, mandatory
|
61
61
|
def extract_environment_from_doc(doc, env_to_populate)
|
62
|
-
env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{
|
62
|
+
env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{EEML5_HREF}")
|
63
63
|
return extract_environment_from_node(env_node, env_to_populate)
|
64
64
|
end
|
65
65
|
|
@@ -67,24 +67,23 @@ module Eeml
|
|
67
67
|
def extract_environment_from_node(env_node, env_to_populate)
|
68
68
|
env = env_to_populate
|
69
69
|
env.identifier = env_node['id']
|
70
|
-
env.updated = Time.
|
71
|
-
|
70
|
+
env.updated = Time.gm(*ParseDate.parsedate(env_node['updated'])).utc if !env_node['updated'].nil?
|
72
71
|
|
73
72
|
env.creator = env_node['creator']
|
74
73
|
|
75
|
-
env.title = optional_content(env_node, 'x:title', 'title', "x:#{
|
76
|
-
env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{
|
77
|
-
env.description = optional_content(env_node, 'x:description', 'description', "x:#{
|
78
|
-
env.website = optional_content(env_node, 'x:website', 'website', "x:#{
|
79
|
-
env.status = optional_content(env_node, 'x:status', 'status', "x:#{
|
80
|
-
env.email = optional_content(env_node, 'x:email', 'email', "x:#{
|
81
|
-
env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{
|
74
|
+
env.title = optional_content(env_node, 'x:title', 'title', "x:#{EEML5_HREF}")
|
75
|
+
env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{EEML5_HREF}")
|
76
|
+
env.description = optional_content(env_node, 'x:description', 'description', "x:#{EEML5_HREF}")
|
77
|
+
env.website = optional_content(env_node, 'x:website', 'website', "x:#{EEML5_HREF}")
|
78
|
+
env.status = optional_content(env_node, 'x:status', 'status', "x:#{EEML5_HREF}")
|
79
|
+
env.email = optional_content(env_node, 'x:email', 'email', "x:#{EEML5_HREF}")
|
80
|
+
env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{EEML5_HREF}")
|
82
81
|
|
83
82
|
#find_first_node_or_fail(env_node, 'x:location', 'location')
|
84
|
-
loc_node = env_node.find_first('x:location', "x:#{
|
83
|
+
loc_node = env_node.find_first('x:location', "x:#{EEML5_HREF}")
|
85
84
|
env.location = extractLocation(loc_node) if loc_node
|
86
85
|
|
87
|
-
datastream_nodes = env_node.find('x:data', "x:#{
|
86
|
+
datastream_nodes = env_node.find('x:data', "x:#{EEML5_HREF}")
|
88
87
|
# raise NoDataStreams.new, "no datastreams found" if datastream_nodes.empty?
|
89
88
|
env.datastreams = extractDataStreams(datastream_nodes) unless datastream_nodes.empty?
|
90
89
|
|
@@ -102,10 +101,10 @@ module Eeml
|
|
102
101
|
loc.domain = node['domain']
|
103
102
|
loc.disposition = node['disposition']
|
104
103
|
loc.exposure = node['exposure']
|
105
|
-
loc.name = optional_content(node, 'x:name', 'name', "x:#{
|
106
|
-
loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{
|
107
|
-
loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{
|
108
|
-
loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{
|
104
|
+
loc.name = optional_content(node, 'x:name', 'name', "x:#{EEML5_HREF}")
|
105
|
+
loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{EEML5_HREF}")
|
106
|
+
loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{EEML5_HREF}")
|
107
|
+
loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{EEML5_HREF}")
|
109
108
|
return loc
|
110
109
|
end
|
111
110
|
|
@@ -139,20 +138,24 @@ module Eeml
|
|
139
138
|
data = DataStream.new
|
140
139
|
raise MissingAttribute.new(node.name, 'id') if node['id'].nil?
|
141
140
|
data.identifier = node['id']
|
142
|
-
node.find('x:tag', "x:#{
|
141
|
+
node.find('x:tag', "x:#{EEML5_HREF}").each do |tag_node|
|
143
142
|
data.tags << tag_node.content.strip
|
144
143
|
end
|
145
144
|
|
146
|
-
value_nodes = node.find('x:value', "x:#{
|
145
|
+
value_nodes = node.find('x:value', "x:#{EEML5_HREF}")
|
147
146
|
raise exception_for_node(node, DataMissingValue, "Data node is missing value node.") if value_nodes.empty?
|
148
147
|
raise exception_for_node(node, DataHasMultipleValues, "Data node has multiple 'value' nodes.") if value_nodes.size > 1
|
149
148
|
|
150
149
|
value_node = value_nodes.first
|
151
|
-
data.min_value = value_node['minValue']
|
152
|
-
data.max_value = value_node['maxValue']
|
153
|
-
data.value = value_node.content.strip
|
154
150
|
|
155
|
-
|
151
|
+
value = Value.new
|
152
|
+
value.min_value = value_node['minValue']
|
153
|
+
value.max_value = value_node['maxValue']
|
154
|
+
value.value = value_node.content.strip
|
155
|
+
|
156
|
+
data.add_value(value)
|
157
|
+
|
158
|
+
unit_nodes = node.find('x:unit', "x:#{EEML5_HREF}")
|
156
159
|
raise exception_for_node(node, DataHasMultipleUnits, "Data node has multiple 'unit' nodes.") if unit_nodes.size > 1
|
157
160
|
|
158
161
|
unit_node = unit_nodes.first
|
data/lib/eeml/output_registry.rb
CHANGED
@@ -4,11 +4,11 @@ require 'eeml/json_output'
|
|
4
4
|
module Eeml
|
5
5
|
class OutputRegistry # :nodoc:
|
6
6
|
#look at the given xml, build and return a new v005 or 006 parser, accordingly
|
7
|
-
def self.get_xml_output_for(version =
|
7
|
+
def self.get_xml_output_for(version = EEML5_VERSION)
|
8
8
|
LibXMLEemlOutputV005.new
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.get_json_output_for(version =
|
11
|
+
def self.get_json_output_for(version = EEML5_VERSION)
|
12
12
|
JsonOutput.new
|
13
13
|
end
|
14
14
|
|
data/lib/eeml.rb
CHANGED
@@ -8,13 +8,14 @@ require 'json'
|
|
8
8
|
require 'eeml/constants'
|
9
9
|
require 'eeml/exceptions'
|
10
10
|
require 'eeml/environment'
|
11
|
-
require 'eeml/
|
11
|
+
require 'eeml/environment_builder'
|
12
12
|
require 'eeml/output_registry'
|
13
|
+
require 'time'
|
13
14
|
|
14
15
|
module Eeml
|
15
16
|
|
16
17
|
# library version number
|
17
|
-
VERSION = '0.0.
|
18
|
+
VERSION = '0.0.8'
|
18
19
|
|
19
20
|
# TODO: put in some configuration file, not here
|
20
21
|
LOCAL_EEML_SCHEMA_LOCATION = 'schemas/eeml/005.xsd'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
{"datastreams":[
|
2
|
+
{"tags":["tagD0"],
|
3
|
+
"values":[{"value":"0","min_value":"-9999.0","max_value":"1022.0","recorded_at":"2009-02-11T10:56:56Z"}],
|
4
|
+
"unit":{"type":"basicSI","label":"Celsius","symbol":"C"},
|
5
|
+
"id":"0"},
|
6
|
+
{"values":[{"value":"33","min_value":"0.0","max_value":"1023.0","recorded_at":"2009-02-11T10:56:55Z"}],
|
7
|
+
"id":"1"},
|
8
|
+
{"tags":["tagD2a","tagD2b","tagD2c"],
|
9
|
+
"values":[{"value":"42.1","min_value":"23.4","max_value":"1021.0","recorded_at":"2009-02-11T10:55:10Z"}],
|
10
|
+
"id":"2"}
|
11
|
+
],
|
12
|
+
"description":"description here",
|
13
|
+
"updated":"2009-02-11T10:56:56Z",
|
14
|
+
"status":"frozen",
|
15
|
+
"website":"http:\/\/example.com\/studio\/",
|
16
|
+
"email":"someone@example.com",
|
17
|
+
"feed":"http:\/\/example.com\/api\/1247.xml",
|
18
|
+
"location":{
|
19
|
+
"lat":"50.1",
|
20
|
+
"lon":"48.7",
|
21
|
+
"ele":"1.34",
|
22
|
+
"name":"Up on the roof (somewhere)",
|
23
|
+
"domain":"physical",
|
24
|
+
"exposure":"outdoor",
|
25
|
+
"disposition":"mobile"
|
26
|
+
},
|
27
|
+
"icon":"http:\/\/example.com\/some\/icon.gif",
|
28
|
+
"id":"1247",
|
29
|
+
"title":"title here",
|
30
|
+
"version":"0.6"}
|
data/test/test_environment.rb
CHANGED
@@ -149,7 +149,7 @@ class TestEnvironment < Test::Unit::TestCase
|
|
149
149
|
assert_equal('http://example.com/some/icon.gif', env.icon)
|
150
150
|
#env attrs
|
151
151
|
assert_equal('1247', env.identifier)
|
152
|
-
assert_equal('2009-02-11T10:56:56Z', env.updated.
|
152
|
+
assert_equal('2009-02-11T10:56:56Z', env.updated.utc.iso8601)
|
153
153
|
assert_equal('http://example.com/creator/', env.creator)
|
154
154
|
end
|
155
155
|
|
@@ -312,7 +312,7 @@ class TestEnvironment < Test::Unit::TestCase
|
|
312
312
|
|
313
313
|
#env attrs
|
314
314
|
assert_equal('1247', env.identifier)
|
315
|
-
assert_equal('2009-02-11T10:56:56Z', env.updated.
|
315
|
+
assert_equal('2009-02-11T10:56:56Z', env.updated.utc.iso8601)
|
316
316
|
end
|
317
317
|
|
318
318
|
test "location parses ok from json" do
|
@@ -360,6 +360,68 @@ class TestEnvironment < Test::Unit::TestCase
|
|
360
360
|
end
|
361
361
|
end
|
362
362
|
|
363
|
+
test "parses a v6 input file ok" do
|
364
|
+
env = create_env_from_json_v6_file_one
|
365
|
+
assert_not_nil env
|
366
|
+
assert_instance_of Environment, env
|
367
|
+
assert_equal('title here', env.title)
|
368
|
+
assert_equal('description here', env.description)
|
369
|
+
assert_equal('http://example.com/api/1247.xml', env.feed_url)
|
370
|
+
assert_equal('http://example.com/studio/', env.website)
|
371
|
+
assert_equal('frozen', env.status)
|
372
|
+
assert_equal('someone@example.com', env.email)
|
373
|
+
assert_equal('http://example.com/some/icon.gif', env.icon)
|
374
|
+
|
375
|
+
#env attrs
|
376
|
+
assert_equal('1247', env.identifier)
|
377
|
+
assert_equal('2009-02-11T10:56:56Z', env.updated.utc.iso8601)
|
378
|
+
end
|
379
|
+
|
380
|
+
test "location parses ok from json when parsing a v6 file" do
|
381
|
+
env = create_env_from_json_v6_file_one
|
382
|
+
assert_not_nil env.location
|
383
|
+
location = env.location
|
384
|
+
assert_equal "Up on the roof (somewhere)", location.name
|
385
|
+
assert_equal "50.1", location.latitude
|
386
|
+
assert_equal "48.7", location.longitude
|
387
|
+
assert_equal "1.34", location.elevation
|
388
|
+
assert_equal "physical", location.domain
|
389
|
+
assert_equal "outdoor", location.exposure
|
390
|
+
assert_equal "mobile", location.disposition
|
391
|
+
end
|
392
|
+
|
393
|
+
test "datastreams parse ok from v6 json" do
|
394
|
+
env = create_env_from_json_v6_file_one
|
395
|
+
assert_equal 3, env.datastreams.size
|
396
|
+
|
397
|
+
#the expected values for the datastreams in the test doc
|
398
|
+
expectations_list = [
|
399
|
+
#id, tag array, min, max, value, unit_symbol, unit_type, unit_value
|
400
|
+
['0', ['tagD0'], '-9999.0', '1022.0', '0', 'C', 'basicSI', 'Celsius'],
|
401
|
+
['1', [], '0.0', '1023.0', '33', nil, nil, nil],
|
402
|
+
['2', ['tagD2a', 'tagD2b', 'tagD2c'], '23.4', '1021.0', '42.1', nil, nil, nil]
|
403
|
+
]
|
404
|
+
env.datastreams.each_with_index do |ds, i|
|
405
|
+
|
406
|
+
e_identifier, e_tags, e_min_value, e_max_value, e_value, e_unit_symbol, e_unit_type, e_unit_value = expectations_list[i]
|
407
|
+
|
408
|
+
assert_equal e_identifier, ds.identifier
|
409
|
+
|
410
|
+
assert_equal e_tags.size, ds.tags.size, "should have right num of tags"
|
411
|
+
|
412
|
+
e_tags.each do |expected_tag|
|
413
|
+
ds.tags.member? expected_tag
|
414
|
+
end
|
415
|
+
|
416
|
+
assert_equal e_min_value, ds.min_value
|
417
|
+
assert_equal e_max_value, ds.max_value
|
418
|
+
assert_equal e_value, ds.value
|
419
|
+
assert_equal e_unit_symbol, ds.unit_symbol
|
420
|
+
assert_equal e_unit_type, ds.unit_type
|
421
|
+
assert_equal e_unit_value, ds.unit_value
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
363
425
|
# --- -------------------------------------------------------
|
364
426
|
# --- csv input stuff -------------------------------------------------------
|
365
427
|
# --- -------------------------------------------------------
|
@@ -379,7 +441,7 @@ class TestEnvironment < Test::Unit::TestCase
|
|
379
441
|
#TODO: note, can't unload the class before other tests, so be careful with this approach to conveniences.
|
380
442
|
class Eeml::Environment
|
381
443
|
def values_quick
|
382
|
-
datastreams.map {|ds| ds.value}
|
444
|
+
datastreams.map {|ds| ds.values.last.value}
|
383
445
|
end
|
384
446
|
end
|
385
447
|
|
@@ -448,7 +510,7 @@ class TestEnvironment < Test::Unit::TestCase
|
|
448
510
|
expected_json = File.read('test/data/doc_2_expected.json').rstrip
|
449
511
|
expected_hash = JSON.parse(expected_json)
|
450
512
|
output_hash = JSON.parse(output_json)
|
451
|
-
|
513
|
+
assert_json_hashes_equal(expected_hash, output_hash)
|
452
514
|
end
|
453
515
|
|
454
516
|
test "basic output in public json format - no location" do
|
@@ -516,6 +578,10 @@ class TestEnvironment < Test::Unit::TestCase
|
|
516
578
|
return create_env_from_json_file('test/data/doc_1.json')
|
517
579
|
end
|
518
580
|
|
581
|
+
def create_env_from_json_v6_file_one
|
582
|
+
return create_env_from_json_file('test/data/doc_1_v6.json')
|
583
|
+
end
|
584
|
+
|
519
585
|
def create_env_from_json_file(filename)
|
520
586
|
json = File.read(filename)
|
521
587
|
return Environment.new_from_json(json)
|
@@ -525,8 +591,4 @@ class TestEnvironment < Test::Unit::TestCase
|
|
525
591
|
return nil if json.nil?
|
526
592
|
json.gsub(/","/, '"' + "\n" + '"').sort
|
527
593
|
end
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
594
|
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.
|
4
|
+
version: 0.0.8
|
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-
|
33
|
+
date: 2009-11-21 00:00:00 +00:00
|
34
34
|
default_executable:
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
@@ -100,13 +100,14 @@ extra_rdoc_files:
|
|
100
100
|
- lib/eeml/constants.rb
|
101
101
|
- lib/eeml/csv_parser.rb
|
102
102
|
- lib/eeml/environment.rb
|
103
|
+
- lib/eeml/environment_builder.rb
|
103
104
|
- lib/eeml/exceptions.rb
|
104
105
|
- lib/eeml/json_environment_parser_v005.rb
|
106
|
+
- lib/eeml/json_environment_parser_v006.rb
|
105
107
|
- lib/eeml/json_output.rb
|
106
108
|
- lib/eeml/libxml_eeml_output_v005.rb
|
107
109
|
- lib/eeml/libxml_eeml_parser_v005.rb
|
108
110
|
- lib/eeml/output_registry.rb
|
109
|
-
- lib/eeml/parser_registry.rb
|
110
111
|
files:
|
111
112
|
- CHANGELOG
|
112
113
|
- LICENSE
|
@@ -119,18 +120,20 @@ files:
|
|
119
120
|
- lib/eeml/constants.rb
|
120
121
|
- lib/eeml/csv_parser.rb
|
121
122
|
- lib/eeml/environment.rb
|
123
|
+
- lib/eeml/environment_builder.rb
|
122
124
|
- lib/eeml/exceptions.rb
|
123
125
|
- lib/eeml/json_environment_parser_v005.rb
|
126
|
+
- lib/eeml/json_environment_parser_v006.rb
|
124
127
|
- lib/eeml/json_output.rb
|
125
128
|
- lib/eeml/libxml_eeml_output_v005.rb
|
126
129
|
- lib/eeml/libxml_eeml_parser_v005.rb
|
127
130
|
- lib/eeml/output_registry.rb
|
128
|
-
- lib/eeml/parser_registry.rb
|
129
131
|
- schemas/eeml/005.xsd
|
130
132
|
- test/data/complete_namespaced.xml
|
131
133
|
- test/data/difficult_tag.xml
|
132
134
|
- test/data/doc_1.json
|
133
135
|
- test/data/doc_1.xml
|
136
|
+
- test/data/doc_1_v6.json
|
134
137
|
- test/data/doc_2.xml
|
135
138
|
- test/data/doc_2_expected.json
|
136
139
|
- test/data/list.xml
|
metadata.gz.sig
CHANGED
Binary file
|
data/lib/eeml/parser_registry.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'eeml/libxml_eeml_parser_v005'
|
2
|
-
require 'eeml/json_environment_parser_v005'
|
3
|
-
|
4
|
-
module Eeml
|
5
|
-
class ParserRegistry # :nodoc:
|
6
|
-
#look at the given xml, build and return a new v005 or 006 parser, accordingly
|
7
|
-
#this should work whether the xml given is for a single environment, or for a results list
|
8
|
-
def self.get_xml_parser_for(xml_str)
|
9
|
-
LibXMLEemlParserV005.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.get_json_parser_for(json_str)
|
13
|
-
JsonEnvironmentParserV005.new
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|