api06: Move version-checking into the models, raising an exception on mismatch
[rails.git] / app / controllers / way_controller.rb
1 class WayController < ApplicationController
2   require 'xml/libxml'
3
4   session :off
5   before_filter :authorize, :only => [:create, :update, :delete]
6   before_filter :check_write_availability, :only => [:create, :update, :delete]
7   before_filter :check_read_availability, :except => [:create, :update, :delete]
8   after_filter :compress_output
9
10   def create
11     if request.put?
12       way = Way.from_xml(request.raw_post, true)
13
14       if way
15         if !way.preconditions_ok?
16           render :text => "", :status => :precondition_failed
17         else
18           way.version = 0
19           way.user_id = @user.id
20           way.save_with_history!
21
22           render :text => way.id.to_s, :content_type => "text/plain"
23         end
24       else
25         render :nothing => true, :status => :bad_request
26       end
27     else
28       render :nothing => true, :status => :method_not_allowed
29     end
30   end
31
32   def read
33     begin
34       way = Way.find(params[:id])
35
36       response.headers['Last-Modified'] = way.timestamp.rfc822
37
38       if way.visible
39         render :text => way.to_xml.to_s, :content_type => "text/xml"
40       else
41         render :text => "", :status => :gone
42       end
43     rescue ActiveRecord::RecordNotFound
44       render :nothing => true, :status => :not_found
45     end
46   end
47
48   def update
49     begin
50       way = Way.find(params[:id])
51       new_way = Way.from_xml(request.raw_post)
52
53       if new_way and new_way.id == way.id
54         way.update_from(new_way, @user)
55         render :text => way.version.to_s, :content_type => "text/plain"
56       else
57         render :nothing => true, :status => :bad_request
58       end
59     rescue OSM::APIPreconditionFailedError
60       render :text => "", :status => :precondition_failed
61     rescue OSM::APIVersionMismatchError => ex
62       render :text => "Version mismatch: Provided " + ex.provided.to_s +
63         ", server had: " + ex.latest.to_s, :status => :bad_request
64     rescue ActiveRecord::RecordNotFound
65       render :nothing => true, :status => :not_found
66     end
67   end
68
69   # This is the API call to delete a way
70   def delete
71     begin
72       way = Way.find(params[:id])
73       way.delete_with_relations_and_history(@user)
74
75       # if we get here, all is fine, otherwise something will catch below.  
76       render :nothing => true
77     rescue OSM::APIAlreadyDeletedError
78       render :text => "", :status => :gone
79     rescue OSM::APIPreconditionFailedError
80       render :text => "", :status => :precondition_failed
81     rescue ActiveRecord::RecordNotFound
82       render :nothing => true, :status => :not_found
83     end
84   end
85
86   def full
87     begin
88       way = Way.find(params[:id])
89
90       if way.visible
91         nd_ids = way.nds + [-1]
92         nodes = Node.find(:all, :conditions => "visible = 1 AND id IN (#{nd_ids.join(',')})")
93
94         # Render
95         doc = OSM::API.new.get_xml_doc
96         nodes.each do |node|
97           doc.root << node.to_xml_node()
98         end
99         doc.root << way.to_xml_node()
100
101         render :text => doc.to_s, :content_type => "text/xml"
102       else
103         render :text => "", :status => :gone
104       end
105     rescue ActiveRecord::RecordNotFound
106       render :nothing => true, :status => :not_found
107     end
108   end
109
110   def ways
111     begin
112       ids = params['ways'].split(',').collect { |w| w.to_i }
113     rescue
114       ids = []
115     end
116
117     if ids.length > 0
118       doc = OSM::API.new.get_xml_doc
119
120       Way.find(ids).each do |way|
121         doc.root << way.to_xml_node
122       end
123
124       render :text => doc.to_s, :content_type => "text/xml"
125     else
126       render :nothing => true, :status => :bad_request
127     end
128   end
129
130   def ways_for_node
131     wayids = WayNode.find(:all, :conditions => ['node_id = ?', params[:id]]).collect { |ws| ws.id[0] }.uniq
132
133     doc = OSM::API.new.get_xml_doc
134
135     Way.find(wayids).each do |way|
136       doc.root << way.to_xml_node
137     end
138
139     render :text => doc.to_s, :content_type => "text/xml"
140   end
141 end