eeml 0.0.1
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/CHANGELOG +0 -0
- data/LICENSE +25 -0
- data/Manifest +30 -0
- data/README +8 -0
- data/Rakefile +25 -0
- data/eeml.gemspec +46 -0
- data/example.rb +33 -0
- data/lib/blank.rb +50 -0
- data/lib/eeml/constants.rb +17 -0
- data/lib/eeml/csv_parser.rb +16 -0
- data/lib/eeml/environment.rb +113 -0
- data/lib/eeml/exceptions.rb +59 -0
- data/lib/eeml/feed_output.rb +169 -0
- data/lib/eeml/feed_retriever.rb +103 -0
- data/lib/eeml/json_environment_parser.rb +11 -0
- data/lib/eeml/libxml_eeml_output_v005.rb +120 -0
- data/lib/eeml/libxml_eeml_parser_v005.rb +179 -0
- data/lib/eeml/output_registry.rb +13 -0
- data/lib/eeml/parser_registry.rb +14 -0
- data/lib/eeml.rb +35 -0
- data/schemas/eeml/005.xsd +134 -0
- data/test/data/doc_1.json +2 -0
- data/test/data/doc_1.xml +32 -0
- data/test/data/minimal.xml +9 -0
- data/test/data/out_empty.xml +4 -0
- data/test/libxml_test_helper.rb +39 -0
- data/test/test_environment.rb +370 -0
- data/test/test_helper.rb +56 -0
- data/test/test_libxml_eeml_parser_v005.rb +9 -0
- data/test/test_libxml_test_helper.rb +85 -0
- data.tar.gz.sig +1 -0
- metadata +177 -0
- metadata.gz.sig +3 -0
data/CHANGELOG
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2009, Neill Bogie, Samuel Mulube.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
* Neither the name of the <ORGANIZATION> nor the names of its contributors
|
13
|
+
may be used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
19
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
24
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
25
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Manifest
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
example.rb
|
2
|
+
eeml.gemspec
|
3
|
+
LICENSE
|
4
|
+
CHANGELOG
|
5
|
+
README
|
6
|
+
test/test_environment.rb
|
7
|
+
test/test_libxml_test_helper.rb
|
8
|
+
test/libxml_test_helper.rb
|
9
|
+
test/test_libxml_eeml_parser_v005.rb
|
10
|
+
test/test_helper.rb
|
11
|
+
test/data/minimal.xml
|
12
|
+
test/data/out_empty.xml
|
13
|
+
test/data/doc_1.xml
|
14
|
+
test/data/doc_1.json
|
15
|
+
lib/eeml.rb
|
16
|
+
lib/eeml/constants.rb
|
17
|
+
lib/eeml/feed_retriever.rb
|
18
|
+
lib/eeml/json_environment_parser.rb
|
19
|
+
lib/eeml/output_registry.rb
|
20
|
+
lib/eeml/parser_registry.rb
|
21
|
+
lib/eeml/libxml_eeml_output_v005.rb
|
22
|
+
lib/eeml/feed_output.rb
|
23
|
+
lib/eeml/libxml_eeml_parser_v005.rb
|
24
|
+
lib/eeml/exceptions.rb
|
25
|
+
lib/eeml/csv_parser.rb
|
26
|
+
lib/eeml/environment.rb
|
27
|
+
lib/blank.rb
|
28
|
+
schemas/eeml/005.xsd
|
29
|
+
Rakefile
|
30
|
+
Manifest
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "lib"))
|
4
|
+
|
5
|
+
require 'eeml'
|
6
|
+
|
7
|
+
Echoe.new("eeml") do |p|
|
8
|
+
p.author = "Neill Bogie, Sam Mulube"
|
9
|
+
p.email = "sam.mulube@gmail.com"
|
10
|
+
p.description = "Simple little library for programmatically manipulating EEML documents, in particular this library is designed to work with the Pachube web service."
|
11
|
+
p.summary = "Simple little library for programmatically manipulating EEML documents."
|
12
|
+
p.version = Eeml::VERSION
|
13
|
+
p.runtime_dependencies = [
|
14
|
+
"libxml-ruby >= 1.1.3",
|
15
|
+
"json >= 1.1.3"
|
16
|
+
]
|
17
|
+
p.development_dependencies = [
|
18
|
+
"rake >= 0.8.4",
|
19
|
+
"mocha >= 0.9.6"
|
20
|
+
]
|
21
|
+
p.ignore_pattern = [
|
22
|
+
"test/data/real_xmls/v005/oks/*",
|
23
|
+
"test/data/real_xmls/v005/*"
|
24
|
+
]
|
25
|
+
end
|
data/eeml.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{eeml}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Neill Bogie, Sam Mulube"]
|
9
|
+
s.cert_chain = ["/home/sam/.gem/gem-public_cert.pem"]
|
10
|
+
s.date = %q{2009-04-17}
|
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
|
+
s.email = %q{sam.mulube@gmail.com}
|
13
|
+
s.extra_rdoc_files = ["LICENSE", "CHANGELOG", "README", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/feed_retriever.rb", "lib/eeml/json_environment_parser.rb", "lib/eeml/output_registry.rb", "lib/eeml/parser_registry.rb", "lib/eeml/libxml_eeml_output_v005.rb", "lib/eeml/feed_output.rb", "lib/eeml/libxml_eeml_parser_v005.rb", "lib/eeml/exceptions.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/blank.rb"]
|
14
|
+
s.files = ["example.rb", "eeml.gemspec", "LICENSE", "CHANGELOG", "README", "test/test_environment.rb", "test/test_libxml_test_helper.rb", "test/libxml_test_helper.rb", "test/test_libxml_eeml_parser_v005.rb", "test/test_helper.rb", "test/data/minimal.xml", "test/data/out_empty.xml", "test/data/doc_1.xml", "test/data/doc_1.json", "lib/eeml.rb", "lib/eeml/constants.rb", "lib/eeml/feed_retriever.rb", "lib/eeml/json_environment_parser.rb", "lib/eeml/output_registry.rb", "lib/eeml/parser_registry.rb", "lib/eeml/libxml_eeml_output_v005.rb", "lib/eeml/feed_output.rb", "lib/eeml/libxml_eeml_parser_v005.rb", "lib/eeml/exceptions.rb", "lib/eeml/csv_parser.rb", "lib/eeml/environment.rb", "lib/blank.rb", "schemas/eeml/005.xsd", "Rakefile", "Manifest"]
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.homepage = %q{}
|
17
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Eeml", "--main", "README"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{eeml}
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
21
|
+
s.signing_key = %q{/home/sam/.gem/gem-private_key.pem}
|
22
|
+
s.summary = %q{Simple little library for programmatically manipulating EEML documents.}
|
23
|
+
s.test_files = ["test/test_environment.rb", "test/test_libxml_test_helper.rb", "test/test_libxml_eeml_parser_v005.rb", "test/test_helper.rb"]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
+
s.specification_version = 2
|
28
|
+
|
29
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
30
|
+
s.add_runtime_dependency(%q<libxml-ruby>, [">= 0", "= 1.1.3"])
|
31
|
+
s.add_runtime_dependency(%q<json>, [">= 0", "= 1.1.3"])
|
32
|
+
s.add_development_dependency(%q<rake>, [">= 0", "= 0.8.4"])
|
33
|
+
s.add_development_dependency(%q<mocha>, [">= 0", "= 0.9.6"])
|
34
|
+
else
|
35
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0", "= 1.1.3"])
|
36
|
+
s.add_dependency(%q<json>, [">= 0", "= 1.1.3"])
|
37
|
+
s.add_dependency(%q<rake>, [">= 0", "= 0.8.4"])
|
38
|
+
s.add_dependency(%q<mocha>, [">= 0", "= 0.9.6"])
|
39
|
+
end
|
40
|
+
else
|
41
|
+
s.add_dependency(%q<libxml-ruby>, [">= 0", "= 1.1.3"])
|
42
|
+
s.add_dependency(%q<json>, [">= 0", "= 1.1.3"])
|
43
|
+
s.add_dependency(%q<rake>, [">= 0", "= 0.8.4"])
|
44
|
+
s.add_dependency(%q<mocha>, [">= 0", "= 0.9.6"])
|
45
|
+
end
|
46
|
+
end
|
data/example.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#should invoke this with (e.g.) ruby -Ilib example.rb in order to add lib/ to your search path
|
4
|
+
|
5
|
+
require 'rubygems' #only if your libxml is installed under rubygems
|
6
|
+
require 'eeml'
|
7
|
+
|
8
|
+
include Eeml #allows you to refer to Environment rather than Eeml::Environment
|
9
|
+
|
10
|
+
#Example: make an environment from scratch
|
11
|
+
env = Environment.new(:creator => 'http://www.example.com/ourstudio/', :feed_url => 'http://www.example.com/ourstudio/feeds/house.xml')
|
12
|
+
|
13
|
+
env.title = 'my example feed'
|
14
|
+
env.datastreams << DataStream.new(:value => 93.0, :identifier => 'room.1.humidity')
|
15
|
+
env.datastreams << DataStream.new(:value => 91.0, :identifier => 'room.2.humidity')
|
16
|
+
|
17
|
+
#print out its eeml representation
|
18
|
+
puts env.to_eeml
|
19
|
+
|
20
|
+
|
21
|
+
#Example: parse an environment from an eeml doc:
|
22
|
+
eeml_str = File.read('test/data/doc_1.xml')
|
23
|
+
env2 = Environment.new_from_eeml(eeml_str)
|
24
|
+
env2.datastreams.each do |ds|
|
25
|
+
puts "ds %8s value is %6s (min:%8s, max:%8s)" %[ds.identifier, ds.value, ds.min_value, ds.max_value]
|
26
|
+
end
|
27
|
+
|
28
|
+
#TODO: Example: http-fetch an environment
|
29
|
+
|
30
|
+
#TODO: Example: publish an environment to pachube
|
31
|
+
|
32
|
+
#TODO: Example: configure a different logger (to file; to stderr; different timestamp / format; use an existing rails logger)
|
33
|
+
|
data/lib/blank.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
class Object
|
2
|
+
# An object is blank if it's nil, empty, or a whitespace string.
|
3
|
+
# For example, "", " ", nil, [], and {} are blank.
|
4
|
+
#
|
5
|
+
# This simplifies
|
6
|
+
# if !address.nil? && !address.empty?
|
7
|
+
# to
|
8
|
+
# if !address.blank?
|
9
|
+
def blank?
|
10
|
+
respond_to?(:empty?) ? empty? : !self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NilClass #:nodoc:
|
15
|
+
def blank?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class FalseClass #:nodoc:
|
21
|
+
def blank?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class TrueClass #:nodoc:
|
27
|
+
def blank?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Array #:nodoc:
|
33
|
+
alias_method :blank?, :empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
class Hash #:nodoc:
|
37
|
+
alias_method :blank?, :empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
class String #:nodoc:
|
41
|
+
def blank?
|
42
|
+
self !~ /\S/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Numeric #:nodoc:
|
47
|
+
def blank?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Eeml
|
2
|
+
module Constants
|
3
|
+
#LOCAL_EEML_SCHEMA_LOCATION = "schemas/eeml/005.xsd"
|
4
|
+
EEML_HREF = "http://www.eeml.org/xsd/005"
|
5
|
+
EEML_VERSION = "5"
|
6
|
+
EEML_SCHEMA_LOCATION = "http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd"
|
7
|
+
|
8
|
+
EEML_NAMESPACE = ":#{EEML_HREF}"
|
9
|
+
XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
|
10
|
+
|
11
|
+
#TODO: better encapsulated as a set of methods.
|
12
|
+
XML_TIME_FORMAT_STRING = "%Y-%m-%dT%H:%M:%SZ"
|
13
|
+
|
14
|
+
DEFAULT_HOST = 'pachube.com'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Eeml
|
2
|
+
class CsvParser
|
3
|
+
|
4
|
+
#update the datastreams for the given environment, using the content in the given csv string.
|
5
|
+
def update_datastreams_from_csv(csv_content, environment)
|
6
|
+
# split values at commas
|
7
|
+
datastream_values = csv_content.split(/,/)
|
8
|
+
|
9
|
+
# now strip any whitespace
|
10
|
+
datastream_values.map! { |d| d.strip }
|
11
|
+
|
12
|
+
logger.debug("*** New datastream values: #{datastream_values}")
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Eeml
|
2
|
+
include Eeml::Constants
|
3
|
+
|
4
|
+
class Location
|
5
|
+
attr_accessor :name, :latitude, :longitude, :elevation
|
6
|
+
attr_accessor :domain, :exposure, :disposition
|
7
|
+
end
|
8
|
+
|
9
|
+
class DataStream
|
10
|
+
# include FeedOutput::DataStreamNode
|
11
|
+
attr_accessor :identifier, :value, :tags, :min_value, :max_value, :unit_symbol, :unit_type, :unit_value
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@identifier = options[:identifier]
|
15
|
+
@value = options[:value]
|
16
|
+
@max_value = options[:max_value]
|
17
|
+
@min_value = options[:min_value]
|
18
|
+
@tags = []
|
19
|
+
@unit_symbol = options[:unit_symbol]
|
20
|
+
@unit_type = options[:unit_type]
|
21
|
+
@unit_value = options[:unit_value]
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"identifier: '#{@identifier}', value: '#{@value}', min_value: '#{@min_value}', max_value: '#{@max_value}', tags: '#{@tags.join(", ")}'"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class Environment
|
31
|
+
include FeedOutput::EnvironmentNode
|
32
|
+
attr_accessor :identifier, :updated, :creator
|
33
|
+
attr_accessor :title, :description, :feed_url, :website, :email, :icon, :status
|
34
|
+
attr_accessor :location
|
35
|
+
attr_accessor :datastreams
|
36
|
+
|
37
|
+
# stuff so far needed only for FeedOutput module
|
38
|
+
# attr_accessor :retrieved_at
|
39
|
+
|
40
|
+
@@logger = nil
|
41
|
+
def self.logger=(logger)
|
42
|
+
@@logger = logger
|
43
|
+
end
|
44
|
+
|
45
|
+
def logger
|
46
|
+
return @@logger
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(options = {})
|
50
|
+
@datastreams = []
|
51
|
+
@identifier = options[:identifier]
|
52
|
+
@creator = options[:creator]
|
53
|
+
@title = options[:title]
|
54
|
+
@status = options[:status]
|
55
|
+
@feed_url = options[:feed_url]
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_datastream(datastream)
|
59
|
+
#TODO: consider checking for unique identifier
|
60
|
+
datastreams << datastream
|
61
|
+
end
|
62
|
+
|
63
|
+
def remove_last_datastream
|
64
|
+
datastreams.pop
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.new_from_eeml(xml_str)
|
68
|
+
parser = ParserRegistry.get_xml_parser_for(xml_str)
|
69
|
+
return parser.make_environment_from_xml(xml_str)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.new_from_json(json_str)
|
73
|
+
parser = ParserRegistry.get_json_parser_for(json_str)
|
74
|
+
return parser.make_environment_from_json(json_str)
|
75
|
+
end
|
76
|
+
|
77
|
+
def update_datastreams_from_csv_values!(csv_values)
|
78
|
+
|
79
|
+
csv_values.each_with_index do |new_val, index|
|
80
|
+
datastream = datastreams[index]
|
81
|
+
#if we don't have an existing datastream at same index, create new one
|
82
|
+
if datastream.nil?
|
83
|
+
self.datastreams << DataStream.new(:identifier => index, :value => new_val, :ordering => index)
|
84
|
+
else
|
85
|
+
#we had a match, so update the existing datastream
|
86
|
+
datastream.value = new_val
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# if the csv specifies FEWER feeds than the env currently has.
|
91
|
+
if csv_values.size < self.datastreams.size
|
92
|
+
# remove the excess from the end of the env's list.
|
93
|
+
num_extra = datastreams.size - csv_values.size
|
94
|
+
1.upto(num_extra) { remove_last_datastream }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
#--------------------------------------------------------------------------
|
99
|
+
#----- state tracking stuff -----------------------------------------------
|
100
|
+
#--------------------------------------------------------------------------
|
101
|
+
def live?
|
102
|
+
#TODO
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_eeml(version = Constants::EEML_VERSION)
|
107
|
+
outputter = OutputRegistry.get_xml_output_for(version)
|
108
|
+
outputter.to_eeml(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Eeml
|
2
|
+
# exceptions
|
3
|
+
#TODO: have these inherit from a base parser error
|
4
|
+
class Unavailable < StandardError; end
|
5
|
+
class BadResponse < StandardError; end
|
6
|
+
class ApiKeyMissing < StandardError; end
|
7
|
+
class AuthenticationFailure < StandardError; end
|
8
|
+
|
9
|
+
class BadEeml < StandardError #eeml being parsed was ok xml but bad eeml
|
10
|
+
attr_accessor :line_num, :node_name #no guarantees either is available
|
11
|
+
def to_s
|
12
|
+
extras = []
|
13
|
+
extras << " node name: '" + node_name + "'" if node_name
|
14
|
+
extras << " line_num: #{line_num}" if line_num
|
15
|
+
super.to_s + extras.join(',')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class BadXML < StandardError; end #xml being parsed was malformed
|
20
|
+
class DataMissingValue < BadEeml; end
|
21
|
+
class DataHasMultipleUnits < BadEeml; end
|
22
|
+
class DataHasMultipleValues < BadEeml; end
|
23
|
+
class NoDataStreams < BadEeml; end
|
24
|
+
|
25
|
+
|
26
|
+
#A structured exception which holds info about what was missing and from where.
|
27
|
+
#Note: Some reasons we don't just hold everything in an unstructured exception message:
|
28
|
+
#1. some bits might be useful for dev but not for the public,
|
29
|
+
#2. testing is simplified by having the missing node name recorded explicitly (rather than in a human-readable, changeable string).
|
30
|
+
class MissingNode < BadEeml
|
31
|
+
attr_accessor :base_node_name, :sought_description, :sought_xpath
|
32
|
+
|
33
|
+
def initialize(base_node_name, sought_description, sought_xpath = nil)
|
34
|
+
@base_node_name = base_node_name
|
35
|
+
@sought_description = sought_description
|
36
|
+
@sought_xpath = sought_xpath
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"Missing '#@sought_description' node from base node: '#@base_node_name'" +
|
41
|
+
(@sought_xpath ? "with xpath: '#@sought_xpath'" : "")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class MissingAttribute < BadEeml
|
47
|
+
attr_accessor :node_name, :attribute_name
|
48
|
+
|
49
|
+
def initialize(node_name, attribute_name)
|
50
|
+
@node_name = node_name
|
51
|
+
@attribute_name = attribute_name
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
"Missing attribute '#@attribute_name' from node '#@node_name'"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module FeedOutput # :nodoc:
|
2
|
+
#TODO: move away from mixins for this functionality.
|
3
|
+
#TODO: This is v005-specific.
|
4
|
+
module EnvironmentNode # :nodoc:
|
5
|
+
include LibXML
|
6
|
+
#assumes a logger()
|
7
|
+
#assumes retrieved_at()
|
8
|
+
|
9
|
+
#TODO: Move these (now unused) methods to the publisher (e.g. a rails controller?) which will decide where it's going to host the env,
|
10
|
+
# and which will set the feed property accordingly before serialising the env.
|
11
|
+
# def public_feed_url
|
12
|
+
# return "http://#{DEFAULT_HOST}/api/#{self.id}.xml"
|
13
|
+
# end
|
14
|
+
|
15
|
+
# def public_csv_url
|
16
|
+
# return "http://#{DEFAULT_HOST}/api/#{self.id}.csv"
|
17
|
+
# end
|
18
|
+
|
19
|
+
# def public_json_url
|
20
|
+
# return "http://#{DEFAULT_HOST}/api/#{self.id}.json"
|
21
|
+
# end
|
22
|
+
|
23
|
+
|
24
|
+
def create_eeml_document
|
25
|
+
doc = XML::Document.new
|
26
|
+
eeml = doc.root = XML::Node.new('eeml')
|
27
|
+
XML::Namespace.new(eeml, nil, Eeml::EEML_HREF)
|
28
|
+
XML::Namespace.new(eeml, 'xsi', Eeml::XSI_NAMESPACE)
|
29
|
+
eeml['version'] = Eeml::EEML_VERSION
|
30
|
+
eeml['xsi:schemaLocation'] = Eeml::EEML_SCHEMA_LOCATION
|
31
|
+
return doc
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a csv representation of this environment by iterating through all datastreams and returning
|
35
|
+
# their values.
|
36
|
+
def to_csv
|
37
|
+
return self.datastreams.map { |d| d.value }.join(",")
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create an xml representation of this environment. The document returned should be valid EEML.
|
41
|
+
# def to_eeml(options = { :full => true })
|
42
|
+
# # Returns the public feed URL for this environment.
|
43
|
+
|
44
|
+
|
45
|
+
# logger.debug("*** Returning eeml representation of environment: #{self.identifier}")
|
46
|
+
|
47
|
+
# doc = create_eeml_document
|
48
|
+
|
49
|
+
# doc.root << to_xml_node(options)
|
50
|
+
|
51
|
+
# return doc.to_s(:encoding => XML::Encoding::UTF_8)
|
52
|
+
# end
|
53
|
+
|
54
|
+
def to_xml_node_old(options = { :full => true })
|
55
|
+
logger.debug("*** Creating xml node for environment: #{self.identifier}")
|
56
|
+
|
57
|
+
environment_node = XML::Node.new('environment')
|
58
|
+
#TODO: this was retrieved_at in the db, but it's 'updated' in the xml. Clarify w sam...
|
59
|
+
# ... env.retrieved_at doesn't make much sense to clients generating eeml using the gem.
|
60
|
+
environment_node['updated'] = self.updated.strftime(XML_TIME_FORMAT_STRING) unless self.updated.nil?
|
61
|
+
environment_node['id'] = self.identifier.to_s unless self.identifier.blank?
|
62
|
+
#TODO: write all these strings out safely for xml
|
63
|
+
environment_node['creator'] = self.creator.to_s unless self.creator.blank?
|
64
|
+
|
65
|
+
#TODO: these all should really appear, even when absent? likely make conditional.
|
66
|
+
unless self.title.blank?
|
67
|
+
environment_node << title_node = XML::Node.new('title')
|
68
|
+
title_node << self.title
|
69
|
+
end
|
70
|
+
|
71
|
+
unless self.feed_url.blank?
|
72
|
+
environment_node << feed_node = XML::Node.new('feed')
|
73
|
+
feed_node << self.feed_url
|
74
|
+
end
|
75
|
+
|
76
|
+
unless self.status.blank?
|
77
|
+
environment_node << status_node = XML::Node.new('status')
|
78
|
+
status_node << self.status
|
79
|
+
end
|
80
|
+
|
81
|
+
unless self.description.blank?
|
82
|
+
environment_node << description_node = XML::Node.new('description')
|
83
|
+
description_node << self.description
|
84
|
+
end
|
85
|
+
|
86
|
+
unless self.icon.blank?
|
87
|
+
environment_node << icon_node = XML::Node.new('icon')
|
88
|
+
icon_node << self.icon
|
89
|
+
end
|
90
|
+
|
91
|
+
unless self.website.blank?
|
92
|
+
environment_node << website_node = XML::Node.new('website')
|
93
|
+
website_node << self.website
|
94
|
+
end
|
95
|
+
|
96
|
+
unless self.email.blank?
|
97
|
+
environment_node << email_node = XML::Node.new('email')
|
98
|
+
email_node << self.email
|
99
|
+
end
|
100
|
+
|
101
|
+
unless self.location.nil?
|
102
|
+
environment_node << location_node = XML::Node.new('location')
|
103
|
+
location_node['domain'] = self.location.domain
|
104
|
+
location_node['exposure'] = self.location.exposure unless self.location.exposure.blank?
|
105
|
+
location_node['disposition'] = self.location.disposition unless self.location.disposition.blank?
|
106
|
+
|
107
|
+
unless self.location.name.blank?
|
108
|
+
location_node << location_name_node = XML::Node.new('name')
|
109
|
+
location_name_node << self.location.name
|
110
|
+
end
|
111
|
+
|
112
|
+
location_node << lat_node = XML::Node.new('lat')
|
113
|
+
lat_node << self.location.latitude
|
114
|
+
|
115
|
+
location_node << lng_node = XML::Node.new('lon')
|
116
|
+
lng_node << self.location.longitude
|
117
|
+
|
118
|
+
unless self.location.elevation.blank?
|
119
|
+
location_node << elevation_node = XML::Node.new('ele')
|
120
|
+
elevation_node << self.location.elevation
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
if options[:full] == true
|
125
|
+
self.datastreams.each do |datastream|
|
126
|
+
environment_node << datastream.to_xml_node unless datastream.nil?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
return environment_node
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
module DataStreamNode # :nodoc:
|
137
|
+
include LibXML
|
138
|
+
# Create and return an XML::Node object representing this datastream. This method creates all
|
139
|
+
# required child nodes of the datastream object, including the list of tag elements, any units element
|
140
|
+
# and the value.
|
141
|
+
def to_xml_node
|
142
|
+
datastream_node = XML::Node.new('data')
|
143
|
+
datastream_node['id'] = self.identifier.to_s
|
144
|
+
|
145
|
+
self.tags.each do |tag|
|
146
|
+
tag_node = XML::Node.new('tag')
|
147
|
+
tag_node << tag
|
148
|
+
datastream_node << tag_node
|
149
|
+
end
|
150
|
+
|
151
|
+
datastream_node << value_node = XML::Node.new('value')
|
152
|
+
|
153
|
+
value_node['minValue'] = self.min_value.to_s unless self.min_value.to_s.empty?
|
154
|
+
value_node['maxValue'] = self.max_value.to_s unless self.max_value.to_s.empty?
|
155
|
+
|
156
|
+
value_node << self.value.to_s
|
157
|
+
|
158
|
+
unless self.unit_value.to_s.empty? && self.unit_type.to_s.empty? && self.unit_symbol.to_s.empty?
|
159
|
+
datastream_node << unit_node = XML::Node.new('unit')
|
160
|
+
unit_node['type'] = self.unit_type.to_s unless self.unit_type.to_s.empty?
|
161
|
+
unit_node['symbol'] = self.unit_symbol.to_s unless self.unit_symbol.to_s.empty?
|
162
|
+
unit_node << self.unit_value.to_s unless self.unit_value.to_s.empty?
|
163
|
+
end
|
164
|
+
|
165
|
+
return datastream_node
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|