openstreetmap 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ require 'httparty'
2
+ require 'xml/libxml'
3
+ class OpenStreetMap::Parser < HTTParty::Parser
4
+ include LibXML::XML::SaxParser::Callbacks
5
+
6
+ attr_accessor :context, :description, :lang, :collection
7
+
8
+ def parse
9
+ return nil if body.nil? || body.empty?
10
+ if supports_format?
11
+ self.send(format) # This is a hack, cause the xml format would not be recognized ways, but for nodes and relations
12
+ else
13
+ body
14
+ end
15
+ end
16
+
17
+ def xml
18
+ @parser = LibXML::XML::SaxParser.string(body)
19
+ @parser.callbacks = self
20
+ @parser.parse
21
+ @collection.empty? ? @context : @collection
22
+ end
23
+
24
+ def plain
25
+ body
26
+ end
27
+
28
+ def on_start_document # :nodoc:
29
+ @collection = []
30
+ start_document if respond_to?(:start_document)
31
+ end
32
+
33
+ def on_end_document # :nodoc:
34
+ end_document if respond_to?(:end_document)
35
+ end
36
+
37
+ def on_start_element(name, attr_hash) # :nodoc:
38
+ case name
39
+ when 'node' then _start_node(attr_hash)
40
+ when 'way' then _start_way(attr_hash)
41
+ when 'relation' then _start_relation(attr_hash)
42
+ when 'changeset' then _start_changeset(attr_hash)
43
+ when 'user' then _start_user(attr_hash)
44
+ when 'tag' then _tag(attr_hash)
45
+ when 'nd' then _nd(attr_hash)
46
+ when 'member' then _member(attr_hash)
47
+ when 'home' then _home(attr_hash)
48
+ when 'description' then @description = true
49
+ when 'lang' then @lang = true
50
+ end
51
+ end
52
+
53
+ def on_end_element(name) # :nodoc:
54
+ case name
55
+ when 'description' then @description = false
56
+ when 'lang' then @lang = false
57
+ when 'changeset' then _end_changeset
58
+ end
59
+ end
60
+
61
+ def on_characters(chars)
62
+ if @context.class.name == 'OpenStreetMap::User'
63
+ if @description
64
+ @context.description = chars
65
+ end
66
+ if @lang
67
+ @context.languages << chars
68
+ end
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def _start_node(attr_hash)
75
+ @context = OpenStreetMap::Node.new(attr_hash)
76
+ end
77
+
78
+ def _start_way(attr_hash)
79
+ @context = OpenStreetMap::Way.new(attr_hash)
80
+ end
81
+
82
+ def _start_relation(attr_hash)
83
+ @context = OpenStreetMap::Relation.new(attr_hash)
84
+ end
85
+
86
+ def _start_changeset(attr_hash)
87
+ @context = OpenStreetMap::Changeset.new(attr_hash)
88
+ end
89
+
90
+ def _end_changeset
91
+ @collection << @context
92
+ end
93
+
94
+ def _start_user(attr_hash)
95
+ @context = OpenStreetMap::User.new(attr_hash)
96
+ end
97
+
98
+ def _nd(attr_hash)
99
+ @context << attr_hash['ref']
100
+ end
101
+
102
+ def _tag(attr_hash)
103
+ if respond_to?(:tag)
104
+ return unless tag(@context, attr_hash['k'], attr_value['v'])
105
+ end
106
+ @context.tags.merge!(attr_hash['k'] => attr_hash['v'])
107
+ end
108
+
109
+ def _member(attr_hash)
110
+ new_member = OpenStreetMap::Member.new(attr_hash['type'], attr_hash['ref'], attr_hash['role'])
111
+ if respond_to?(:member)
112
+ return unless member(@context, new_member)
113
+ end
114
+ @context.members << new_member
115
+ end
116
+
117
+ def _home(attr_hash)
118
+ @context.lat = attr_hash['lat'] if attr_hash['lat']
119
+ @context.lon = attr_hash['lon'] if attr_hash['lon']
120
+ @context.lon = attr_hash['zoom'] if attr_hash['zoom']
121
+ end
122
+
123
+ end
@@ -0,0 +1,52 @@
1
+ module OpenStreetMap
2
+ # OpenStreetMap Relation.
3
+ #
4
+ # To create a new OpenStreetMap::Relation object:
5
+ # relation = OpenStreetMap::Relation.new()
6
+ #
7
+ # To get a relation from the API:
8
+ # relation = OpenStreetMap::Relation.find(17)
9
+ #
10
+ class Relation < Element
11
+ # Array of Member objects
12
+ attr_reader :members
13
+
14
+ # Create new Relation object.
15
+ #
16
+ # If +id+ is +nil+ a new unique negative ID will be allocated.
17
+ def initialize(attrs)
18
+ attrs.stringify_keys!
19
+ @members = extract_member(attrs['member'])
20
+ super(attrs)
21
+ end
22
+
23
+ def type
24
+ 'relation'
25
+ end
26
+
27
+ # Return XML for this relation. This method uses the Builder library.
28
+ # The only parameter ist the builder object.
29
+ def to_xml(option = {})
30
+ xml = options[:builder] ||= Builder::XmlMarkup.new
31
+ xml.instruct! unless options[:skip_instruct]
32
+ xml.relation(attributes) do
33
+ members.each do |member|
34
+ member.to_xml(:builder => xml, :skip_instruct => true)
35
+ end
36
+ tags.to_xml(:builder => xml, :skip_instruct => true)
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def extract_member(member_array)
43
+ return [] unless member_array && member_array.size > 0
44
+
45
+ member_array.inject([]) do |memo, member|
46
+ class_to_instantize = "OpenStreetMap::#{member['type'].classify}".constantize
47
+ memo << class_to_instantize.new(:id => member['ref'])
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,26 @@
1
+ module OpenStreetMap
2
+ # A collection of OSM tags which can be attached to a Node, Way,
3
+ # or Relation.
4
+ # It is a subclass of Hash.
5
+ class Tags < Hash
6
+
7
+ # Return XML for these tags. This method uses the Builder library.
8
+ # The only parameter ist the builder object.
9
+ def to_xml(options = {})
10
+ xml = options[:builder] ||= Builder::XmlMarkup.new
11
+ xml.instruct! unless options[:skip_instruct]
12
+ each do |key, value|
13
+ xml.tag(:k => key, :v => value)
14
+ end unless empty?
15
+ end
16
+
17
+ # Return string with comma separated key=value pairs.
18
+ #
19
+ # call-seq: to_s -> String
20
+ #
21
+ def to_s
22
+ sort.collect{ |k, v| "#{k}=#{v}" }.join(', ')
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ require 'builder'
2
+ module OpenStreetMap
3
+ class User
4
+ # Unique ID
5
+ attr_reader :id
6
+
7
+ # Display name
8
+ attr_reader :display_name
9
+
10
+ # When this user was created
11
+ attr_reader :account_created
12
+
13
+ # A little prosa about this user
14
+ attr_accessor :description
15
+
16
+ # All languages the user can speak
17
+ attr_accessor :languages
18
+
19
+ # Lat/Lon Coordinates of the users home.
20
+ attr_accessor :lat, :lon, :zoom
21
+
22
+ # A picture from this user
23
+ attr_accessor :img
24
+
25
+ def initialize(attrs = {})
26
+ attrs.stringify_keys!
27
+ @id = attrs['id'].to_i if attrs['id']
28
+ @display_name = attrs['display_name']
29
+ @account_created = Time.parse(attrs['account_created']) rescue nil
30
+ @languages = []
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,84 @@
1
+ module OpenStreetMap
2
+ # OpenStreetMap Way.
3
+ #
4
+ # To create a new OpenStreetMap::Way object:
5
+ # way = OpenStreetMap::Way.new()
6
+ #
7
+ # To get a way from the API:
8
+ # way = OpenStreetMap::Way.find_way(17)
9
+ #
10
+ class Way < Element
11
+ # Array of node IDs in this way.
12
+ attr_reader :nodes
13
+
14
+ # Create new Way object.
15
+ #
16
+ # id:: ID of this way. If +nil+ a new unique negative ID will be allocated.
17
+ # user:: Username
18
+ # timestamp:: Timestamp of last change
19
+ # nodes:: Array of Node objects and/or node IDs
20
+ def initialize(attrs = {})
21
+ attrs.stringify_keys!
22
+ @nodes = []
23
+ super(attrs)
24
+ end
25
+
26
+ def type
27
+ 'Way'
28
+ end
29
+
30
+ # Add one or more tags or nodes to this way.
31
+ #
32
+ # The argument can be one of the following:
33
+ #
34
+ # * If the argument is a Hash or an OSM::Tags object, those tags are added.
35
+ # * If the argument is an OSM::Node object, its ID is added to the list of node IDs.
36
+ # * If the argument is an Integer or String containing an Integer, this ID is added to the list of node IDs.
37
+ # * If the argument is an Array the function is called recursively, i.e. all items in the Array are added.
38
+ #
39
+ # Returns the way to allow chaining.
40
+ #
41
+ # call-seq: way << something -> Way
42
+ #
43
+ def <<(stuff)
44
+ case stuff
45
+ when Array # call this method recursively
46
+ stuff.each do |item|
47
+ self << item
48
+ end
49
+ when OpenStreetMap::Node
50
+ nodes << stuff.id
51
+ when String
52
+ nodes << stuff.to_i
53
+ when Integer
54
+ nodes << stuff
55
+ else
56
+ tags.merge!(stuff)
57
+ end
58
+ self # return self to allow chaining
59
+ end
60
+
61
+
62
+ # The list of attributes for this Way
63
+ def attribute_list # :nodoc:
64
+ [:id, :version, :uid, :user, :timestamp, :changeset]
65
+ end
66
+
67
+ def self.from_xml(xml_string)
68
+ Parser.call(xml_string, :xml)
69
+ end
70
+
71
+ def to_xml(options = {})
72
+ xml = options[:builder] ||= Builder::XmlMarkup.new
73
+ xml.instruct! unless options[:skip_instruct]
74
+ xml.osm do
75
+ xml.way(attributes) do
76
+ nodes.each do |node_id|
77
+ xml.nd(:ref => node_id)
78
+ end unless nodes.empty?
79
+ tags.to_xml(:builder => xml, :skip_instruct => true)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,31 @@
1
+ require 'hash'
2
+ require 'active_model'
3
+ require 'changeset_callbacks'
4
+ require 'open_street_map/tags'
5
+ require 'open_street_map/element'
6
+ require 'open_street_map/node'
7
+ require 'open_street_map/way'
8
+ require 'open_street_map/changeset'
9
+ require 'open_street_map/relation'
10
+ require 'open_street_map/member'
11
+ require 'open_street_map/user'
12
+ require 'open_street_map/errors'
13
+ require 'open_street_map/basic_auth_client'
14
+ require 'open_street_map/oauth_client'
15
+ require 'open_street_map/parser'
16
+ require 'open_street_map/api'
17
+ require 'oauth'
18
+
19
+ # The OpenStreetMap class handles all calls to the OpenStreetMap API.
20
+ #
21
+ # Usage:
22
+ # require 'osm'
23
+ # auth_client = OpenStreetMap::BasicAuthClient.new(:user_name => 'user', :password => 'a_password')
24
+ # osm = OpenStreetMap.new(auth_client)
25
+ # @node = osm.find_node(1234)
26
+ # @node.tags << {:wheelchair => 'no'}
27
+ # osm.save(@node)
28
+ #
29
+ module OpenStreetMap
30
+
31
+ end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "openstreetmap"
5
+ s.version = "0.2.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Christoph B\u{fc}nte, Enno Brehm"]
9
+ s.date = "2012-03-22"
10
+ s.description = "OpenStreetMap API client for ruby"
11
+ s.email = ["info@christophbuente.de", "guildenstern@gmx.de"]
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "lib/changeset_callbacks.rb", "lib/hash.rb", "lib/open_street_map/api.rb", "lib/open_street_map/basic_auth_client.rb", "lib/open_street_map/changeset.rb", "lib/open_street_map/element.rb", "lib/open_street_map/errors.rb", "lib/open_street_map/member.rb", "lib/open_street_map/node.rb", "lib/open_street_map/oauth_client.rb", "lib/open_street_map/parser.rb", "lib/open_street_map/relation.rb", "lib/open_street_map/tags.rb", "lib/open_street_map/user.rb", "lib/open_street_map/way.rb", "lib/openstreetmap.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "lib/changeset_callbacks.rb", "lib/hash.rb", "lib/open_street_map/api.rb", "lib/open_street_map/basic_auth_client.rb", "lib/open_street_map/changeset.rb", "lib/open_street_map/element.rb", "lib/open_street_map/errors.rb", "lib/open_street_map/member.rb", "lib/open_street_map/node.rb", "lib/open_street_map/oauth_client.rb", "lib/open_street_map/parser.rb", "lib/open_street_map/relation.rb", "lib/open_street_map/tags.rb", "lib/open_street_map/user.rb", "lib/open_street_map/way.rb", "lib/openstreetmap.rb", "openstreetmap.gemspec", "spec/open_street_map/changeset_spec.rb", "spec/open_street_map/node_spec.rb", "spec/open_street_map/relation_spec.rb", "spec/open_street_map/way_spec.rb", "spec/open_street_map_changeset_spec.rb", "spec/open_street_map_node_spec.rb", "spec/open_street_map_way_spec.rb"]
14
+ s.homepage = "https://github.com/sozialhelden/openstreetmap"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Openstreetmap", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = "openstreetmap"
18
+ s.rubygems_version = "1.8.16"
19
+ s.summary = "OpenStreetMap API client for ruby"
20
+
21
+ if s.respond_to? :specification_version then
22
+ s.specification_version = 3
23
+
24
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
25
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
26
+ s.add_runtime_dependency(%q<libxml-ruby>, [">= 0"])
27
+ s.add_runtime_dependency(%q<builder>, [">= 0"])
28
+ s.add_runtime_dependency(%q<oauth>, [">= 0"])
29
+ s.add_runtime_dependency(%q<activemodel>, [">= 0"])
30
+ s.add_development_dependency(%q<echoe>, [">= 0"])
31
+ s.add_development_dependency(%q<rspec>, [">= 0"])
32
+ s.add_development_dependency(%q<webmock>, [">= 0"])
33
+ else
34
+ s.add_dependency(%q<httparty>, [">= 0"])
35
+ s.add_dependency(%q<libxml-ruby>, [">= 0"])
36
+ s.add_dependency(%q<builder>, [">= 0"])
37
+ s.add_dependency(%q<oauth>, [">= 0"])
38
+ s.add_dependency(%q<activemodel>, [">= 0"])
39
+ s.add_dependency(%q<echoe>, [">= 0"])
40
+ s.add_dependency(%q<rspec>, [">= 0"])
41
+ s.add_dependency(%q<webmock>, [">= 0"])
42
+ end
43
+ else
44
+ s.add_dependency(%q<httparty>, [">= 0"])
45
+ s.add_dependency(%q<libxml-ruby>, [">= 0"])
46
+ s.add_dependency(%q<builder>, [">= 0"])
47
+ s.add_dependency(%q<oauth>, [">= 0"])
48
+ s.add_dependency(%q<activemodel>, [">= 0"])
49
+ s.add_dependency(%q<echoe>, [">= 0"])
50
+ s.add_dependency(%q<rspec>, [">= 0"])
51
+ s.add_dependency(%q<webmock>, [">= 0"])
52
+ end
53
+ end
@@ -0,0 +1,90 @@
1
+ require 'openstreetmap'
2
+
3
+ describe 'OpenStreetMap::Changeset' do
4
+
5
+ let :changeset do
6
+ OpenStreetMap::Changeset.new( :id => "123",
7
+ :user => "fred",
8
+ :uid => "123",
9
+ :created_at => "2008-11-08T19:07:39+01:00",
10
+ :open => "true",
11
+ :min_lat => "52.2",
12
+ :max_lat => "52.3",
13
+ :min_lon => "13.4",
14
+ :max_lon => "13.5")
15
+ end
16
+
17
+ it "should have an id attribute set from attributes" do
18
+ changeset.id.should eql(123)
19
+ end
20
+
21
+ it "should have an id attribute within xml representation" do
22
+ changeset.to_xml.should match /id=\"123\"/
23
+ end
24
+
25
+ it "should have a user attributes set from attributes" do
26
+ changeset.user.should eql("fred")
27
+ end
28
+
29
+ it "should have a user attribute within xml representation" do
30
+ changeset.to_xml.should match /user=\"fred\"/
31
+ end
32
+
33
+ it "should have an uid attribute set from attributes" do
34
+ changeset.uid.should eql(123)
35
+ end
36
+
37
+ it "should have an uid attribute within xml representation" do
38
+ changeset.to_xml.should match /uid=\"123\"/
39
+ end
40
+
41
+ it "should have a changeset attributes set from attributes" do
42
+ changeset.should be_open
43
+ end
44
+
45
+ it "should have an open attribute within xml representation" do
46
+ changeset.to_xml.should match /open=\"true\"/
47
+ end
48
+
49
+ it "should have a min_lat attribute set from attributes" do
50
+ changeset.min_lat.should eql(52.2)
51
+ end
52
+
53
+ it "should have a min_lat attribute within xml representation" do
54
+ changeset.to_xml.should match /min_lat=\"52.2\"/
55
+ end
56
+
57
+ it "should have a min_lon attribute set from attributes" do
58
+ changeset.min_lon.should eql(13.4)
59
+ end
60
+
61
+ it "should have a min_lon attribute within xml representation" do
62
+ changeset.to_xml.should match /min_lon=\"13.4\"/
63
+ end
64
+
65
+ it "should have a max_lat attribute set from attributes" do
66
+ changeset.max_lat.should eql(52.3)
67
+ end
68
+
69
+ it "should have a max_lat attribute within xml representation" do
70
+ changeset.to_xml.should match /max_lat=\"52.3\"/
71
+ end
72
+
73
+ it "should have a max_lon attribute set from attributes" do
74
+ changeset.max_lon.should eql(13.5)
75
+ end
76
+
77
+ it "should have a max_lon attribute within xml representation" do
78
+ changeset.to_xml.should match /max_lon=\"13.5\"/
79
+ end
80
+
81
+ it "should have a created_at attribute set from attributes" do
82
+ changeset.created_at.should eql Time.parse('2008-11-08T19:07:39+01:00')
83
+ end
84
+
85
+ it "should have a created_at attribute within xml representation" do
86
+ changeset.to_xml.should match /created_at=\"/
87
+ end
88
+
89
+
90
+ end