xaviershay-kamel 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile ADDED
@@ -0,0 +1,29 @@
1
+ h1. Kamel
2
+
3
+ Create KML files for tasty overlays on google earth and google maps
4
+
5
+ <pre><code>gem install kamel --source http://gems.github.com/</code></pre>
6
+
7
+ h2. Usage
8
+
9
+ <pre><code>require 'rubygems'
10
+ require 'kamel'
11
+
12
+ overlay = Kamel::Overlay.new
13
+ overlay.name = 'Melbourne Train Stations'
14
+ [
15
+ ["Flinders St", -37.818078, 144.966811],
16
+ ["Southern Cross", -37.818358, 144.952417],
17
+ ].each do |name, lat, lng|
18
+ overlay.placemark!(
19
+ :name => name,
20
+ :description => "This is a train station",
21
+ :location => {:lng => lng, :lat => lat},
22
+ :icon => "http://www.uksa.org/images/about/train-icon.gif"
23
+ )
24
+ end
25
+ puts overlay.to_kml</code></pre>
26
+
27
+ h2. Author
28
+
29
+ Xavier Shay ("http://rhnh.net":http://rhnh.net)
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'spec/rake/spectask'
3
+
4
+ Spec::Rake::SpecTask.new do |t|
5
+ t.warning = false
6
+ t.rcov = false
7
+ t.spec_files = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :test => :spec
11
+ task :default => :spec
data/lib/kamel.rb ADDED
@@ -0,0 +1 @@
1
+ require 'kamel/overlay'
@@ -0,0 +1,55 @@
1
+ begin
2
+ require 'kml'
3
+ rescue LoadError
4
+ puts "You must have ruby_kml either installed to use Kamel - either as a gem or available in your path"
5
+ puts "gem install xaviershay-ruby_kml --source http://gems.github.com"
6
+ exit
7
+ end
8
+
9
+ module Kamel
10
+ class Overlay
11
+ attr_accessor :prefix
12
+ attr_accessor :name
13
+ attr_accessor :placemarks
14
+
15
+ def initialize(prefix = '')
16
+ self.prefix = prefix.to_s
17
+ self.placemarks = []
18
+ end
19
+
20
+ def placemark!(attributes)
21
+ self.placemarks << attributes
22
+ end
23
+
24
+ def to_kml
25
+ doc = KML::Document.new
26
+ doc.name = self.name unless self.name.to_s.length == 0
27
+ self.icons.each_with_index {|icon, index|
28
+ doc.styles << KML::Style.new(
29
+ :id => [prefix, 'style', index].join('-'),
30
+ :icon_style => KML::IconStyle.new(
31
+ :icon => KML::Icon.new(:href => icon)
32
+ )
33
+ )
34
+ }
35
+ self.placemarks.each do |placemark|
36
+ attrs = {}
37
+ attrs[:name] = placemark[:name].to_s unless placemark[:name].nil?
38
+ attrs[:description] = placemark[:description].to_s unless placemark[:description].nil?
39
+ attrs[:geometry] = KML::Point.new(:coordinates => placemark[:location]) unless placemark[:location].nil?
40
+ attrs[:style_url] = '#' + [prefix, 'style', self.icons.index(placemark[:icon])].join('-') unless placemark[:icon].nil?
41
+ doc.features << KML::Placemark.new(attrs)
42
+ end
43
+
44
+ kml = KMLFile.new
45
+ kml.objects << doc
46
+ kml.render
47
+ end
48
+
49
+ protected
50
+
51
+ def icons
52
+ self.placemarks.collect {|x| x[:icon]}.compact.uniq.sort
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'rubygems'
3
+ require 'spec'
4
+ require 'kamel'
5
+ require File.dirname(__FILE__) + '/../xpath_matchers'
6
+
7
+
8
+ require 'rexml/document'
9
+ require 'rexml/element'
10
+
11
+ describe Kamel::Overlay, '#to_kml' do
12
+ setup do
13
+ @overlay = Kamel::Overlay.new('test')
14
+ @overlay.placemark!(:name => 'placemark-1', :location => {:lat => 1, :lng => 2}, :description => 'Place 1', :icon => 'icon-1.png')
15
+ @overlay.placemark!(:name => 'placemark-2', :location => "3,4", :description => 'Place 2', :icon => 'icon-1.png')
16
+ @overlay.placemark!(:name => 'placemark-3', :location => [5,6,7], :icon => 'icon-2.png')
17
+ @doc = @overlay.to_kml
18
+ end
19
+
20
+ it 'outputs one style block for each unique icon' do
21
+ @doc.should have_nodes("/kml/Document/Style", 2)
22
+ end
23
+
24
+ it 'outputs one placemark block for each placemark' do
25
+ @doc.should have_nodes("/kml/Document/Placemark", 3)
26
+ end
27
+
28
+ it 'records the name of each placemark' do
29
+ @doc.should match_xpath("/kml/Document/Placemark[1]/name", "placemark-1")
30
+ @doc.should match_xpath("/kml/Document/Placemark[2]/name", "placemark-2")
31
+ @doc.should match_xpath("/kml/Document/Placemark[3]/name", "placemark-3")
32
+ end
33
+
34
+ it 'records the description of each placemark if it is provided' do
35
+ #TODO Figure out how to check for CDATA
36
+ @doc.should have_xpath("/kml/Document/Placemark[1]/description")
37
+ @doc.should have_xpath("/kml/Document/Placemark[2]/description")
38
+ @doc.should_not have_xpath("/kml/Document/Placemark[3]/description")
39
+ end
40
+
41
+ it 'records the location of each placemark' do
42
+ @doc.should match_xpath("/kml/Document/Placemark[1]/Point/coordinates", "2,1")
43
+ @doc.should match_xpath("/kml/Document/Placemark[2]/Point/coordinates", "3,4")
44
+ @doc.should match_xpath("/kml/Document/Placemark[3]/Point/coordinates", "5,6,7")
45
+ end
46
+
47
+ it 'records a styleUrl that matches up to the style block for the given icon' do
48
+ doc = REXML::Document.new(@doc)
49
+ style_ids = REXML::XPath.match(doc, "/kml/Document/Style/IconStyle/Icon/href").inject({}) {|a,v|
50
+ a.update(v.text => '#' + v.parent.parent.parent.attribute('id').value)
51
+ }
52
+ @doc.should match_xpath("/kml/Document/Placemark[1]/styleUrl", style_ids['icon-1.png'])
53
+ @doc.should match_xpath("/kml/Document/Placemark[2]/styleUrl", style_ids['icon-1.png'])
54
+ @doc.should match_xpath("/kml/Document/Placemark[3]/styleUrl", style_ids['icon-2.png'])
55
+ end
56
+ end
@@ -0,0 +1,105 @@
1
+ # http://blog.wolfman.com/articles/2008/01/02/xpath-matchers-for-rspec
2
+
3
+ module Spec
4
+ module Matchers
5
+
6
+ # check if the xpath exists one or more times
7
+ class HaveXpath
8
+ def initialize(xpath)
9
+ @xpath = xpath
10
+ end
11
+
12
+ def matches?(response)
13
+ @response = response
14
+ doc = response.is_a?(REXML::Document) ? response : REXML::Document.new(@response)
15
+ match = REXML::XPath.match(doc, @xpath)
16
+ not match.empty?
17
+ end
18
+
19
+ def failure_message
20
+ "Did not find expected xpath #{@xpath}"
21
+ end
22
+
23
+ def negative_failure_message
24
+ "Did find unexpected xpath #{@xpath}"
25
+ end
26
+
27
+ def description
28
+ "match the xpath expression #{@xpath}"
29
+ end
30
+ end
31
+
32
+ def have_xpath(xpath)
33
+ HaveXpath.new(xpath)
34
+ end
35
+
36
+ # check if the xpath has the specified value
37
+ # value is a string and there must be a single result to match its
38
+ # equality against
39
+ class MatchXpath
40
+ def initialize(xpath, val)
41
+ @xpath = xpath
42
+ @val= val
43
+ end
44
+
45
+ def matches?(response)
46
+ @response = response
47
+ doc = response.is_a?(REXML::Document) ? response : REXML::Document.new(@response)
48
+ ok= true
49
+ REXML::XPath.each(doc, @xpath) do |e|
50
+ @actual_val= case e
51
+ when REXML::Attribute
52
+ e.to_s
53
+ when REXML::Element
54
+ e.text
55
+ else
56
+ e.to_s
57
+ end
58
+ return false unless @val == @actual_val
59
+ end
60
+ return ok
61
+ end
62
+
63
+ def failure_message
64
+ "The xpath #{@xpath} did not have the value '#{@val}'\nIt was '#{@actual_val}'"
65
+ end
66
+
67
+ def description
68
+ "match the xpath expression #{@xpath} with #{@val}"
69
+ end
70
+ end
71
+
72
+ def match_xpath(xpath, val)
73
+ MatchXpath.new(xpath, val)
74
+ end
75
+
76
+ # checks if the given xpath occurs num times
77
+ class HaveNodes #:nodoc:
78
+ def initialize(xpath, num)
79
+ @xpath= xpath
80
+ @num = num
81
+ end
82
+
83
+ def matches?(response)
84
+ @response = response
85
+ doc = response.is_a?(REXML::Document) ? response : REXML::Document.new(@response)
86
+ match = REXML::XPath.match(doc, @xpath)
87
+ @num_found= match.size
88
+ @num_found == @num
89
+ end
90
+
91
+ def failure_message
92
+ "Did not find expected number of nodes #{@num} in xpath #{@xpath}\nFound #{@num_found}"
93
+ end
94
+
95
+ def description
96
+ "match the number of nodes #{@num}"
97
+ end
98
+ end
99
+
100
+ def have_nodes(xpath, num)
101
+ HaveNodes.new(xpath, num)
102
+ end
103
+
104
+ end
105
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xaviershay-kamel
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Xavier Shay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: xaviershay-ruby_kml
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ description: Create KML files for tasty overlays on google earth and google maps
25
+ email: xavier@rhnh.net
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - LICENSE
34
+ - Rakefile
35
+ - README.textile
36
+ - lib/kamel/overlay.rb
37
+ - lib/kamel.rb
38
+ - spec/xpath_matchers.rb
39
+ - spec/kamel/overlay_spec.rb
40
+ has_rdoc: false
41
+ homepage: http://github.com/xaviershay/kamel
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.0.1
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Create KML files for tasty overlays on google earth and google maps
66
+ test_files:
67
+ - spec/kamel/overlay_spec.rb