Add support for segment/:id/ways and node/:id/segments API calls. Fixes #452.
[rails.git] / app / controllers / way_controller.rb
1 class WayController < ApplicationController
2   require 'xml/libxml'
3
4   before_filter :authorize
5   after_filter :compress_output
6
7   def create
8     response.headers["Content-Type"] = 'text/xml'
9     if request.put?
10       way = Way.from_xml(request.raw_post, true)
11
12       if way
13         way.user_id = @user.id
14
15         unless way.preconditions_ok? # are the segments (and their nodes) visible?
16           render :nothing => true, :status => HTTP_PRECONDITION_FAILED
17           return
18         end
19
20         if way.save_with_history
21           render :text => way.id.to_s
22         else
23           render :nothing => true, :status => 500
24         end
25         return
26       else
27         render :nothing => true, :status => 400 # if we got here the doc didnt parse
28         return
29       end
30     end
31
32     render :nothing => true, :status => 500 # something went very wrong
33   end
34
35   def full
36     unless Way.exists?(params[:id])
37       render :nothing => true, :status => 404
38       return
39     end
40
41     way = Way.find(params[:id])
42
43     unless way.visible
44       render :nothing => true, :status => 410
45       return
46     end
47
48     # In future, we might want to do all the data fetch in one step
49     seg_ids = way.segs + [-1]
50     segments = Segment.find_by_sql "select * from current_segments where visible = 1 and id IN (#{seg_ids.join(',')})"
51
52     node_ids = segments.collect {|segment| segment.node_a }
53     node_ids += segments.collect {|segment| segment.node_b }
54     node_ids += [-1]
55     nodes = Node.find(:all, :conditions => "visible = 1 AND id IN (#{node_ids.join(',')})")
56
57     # Render
58     doc = OSM::API.new.get_xml_doc
59     nodes.each do |node|
60       doc.root << node.to_xml_node()
61     end
62     segments.each do |segment|
63       doc.root << segment.to_xml_node()
64     end
65     doc.root << way.to_xml_node()
66
67     render :text => doc.to_s
68   end
69
70   def rest
71     response.headers["Content-Type"] = 'text/xml'
72     unless Way.exists?(params[:id])
73       render :nothing => true, :status => 404
74       return
75     end
76
77     way = Way.find(params[:id])
78
79     case request.method
80
81     when :get
82       unless way.visible
83         render :nothing => true, :status => 410
84         return
85       end
86       render :text => way.to_xml.to_s
87
88     when :delete
89       if way.visible
90         way.visible = false
91         way.save_with_history
92         render :nothing => true
93       else
94         render :nothing => true, :status => 410
95       end
96
97     when :put
98       new_way = Way.from_xml(request.raw_post)
99
100       if new_way
101         unless new_way.preconditions_ok? # are the segments (and their nodes) visible?
102           render :nothing => true, :status => HTTP_PRECONDITION_FAILED
103           return
104         end
105
106         way.user_id = @user.id
107         way.tags = new_way.tags
108         way.segs = new_way.segs
109         way.timestamp = new_way.timestamp
110         way.visible = true
111
112         if way.id == new_way.id and way.save_with_history
113           render :nothing => true
114         else
115           render :nothing => true, :status => 500
116         end
117       else
118         render :nothing => true, :status => 400 # if we got here the doc didnt parse
119       end
120     end
121   end
122
123   def ways
124     response.headers["Content-Type"] = 'text/xml'
125     ids = params['ways'].split(',').collect {|w| w.to_i }
126     if ids.length > 0
127       waylist = Way.find(ids)
128       doc = OSM::API.new.get_xml_doc
129       waylist.each do |way|
130         doc.root << way.to_xml_node
131       end
132       render :text => doc.to_s
133     else
134       render :nothing => true, :status => 400
135     end
136   end
137
138   def ways_for_segment
139     response.headers["Content-Type"] = 'text/xml'
140     wayids = WaySegment.find(:all, :conditions => ['segment_id = ?', params[:id]]).collect { |ws| ws.id }.uniq
141     if wayids.length > 0
142       waylist = Way.find(wayids)
143       doc = OSM::API.new.get_xml_doc
144       waylist.each do |way|
145         doc.root << way.to_xml_node
146       end
147       render :text => doc.to_s
148     else
149       render :nothing => true, :status => 400
150     end
151   end
152
153 end