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