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 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
@@ -0,0 +1,8 @@
1
+ = eeml
2
+
3
+ * http://eeml.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Library for interacting with the API of pachube.com. Also aims to simplify
8
+ the process of creating, parsing and manipulating EEML documents.
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