openstreetmap 0.2.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.
@@ -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