preliminary commit 0.5 API with relations / untested after entity-relation rename...
[rails.git] / app / controllers / relation_controller.rb
1 class RelationController < ApplicationController
2   require 'xml/libxml'
3
4   before_filter :authorize, :only => [:create, :update, :delete]
5   before_filter :check_availability, :only => [:create, :update, :delete]
6
7   after_filter :compress_output
8
9   def create
10     if request.put?
11       relation = Relation.from_xml(request.raw_post, true)
12
13       if relation
14         if !relation.preconditions_ok?
15           render :nothing => true, :status => :precondition_failed
16         else
17           relation.user_id = @user.id
18
19           if relation.save_with_history
20             render :text => relation.id.to_s, :content_type => "text/plain"
21           else
22             print "save error\n";
23             render :nothing => true, :status => :internal_server_error
24           end
25         end
26       else
27         render :nothing => true, :status => :bad_request
28       end
29     else
30       render :nothing => true, :status => :method_not_allowed
31     end
32   end
33
34   def read
35     begin
36       relation = Relation.find(params[:id])
37
38       if relation.visible
39         render :text => relation.to_xml.to_s, :content_type => "text/xml"
40       else
41         render :nothing => true, :status => :gone
42       end
43     rescue ActiveRecord::RecordNotFound
44       render :nothing => true, :status => :not_found
45     rescue
46       render :nothing => true, :status => :internal_server_error
47     end
48   end
49
50   def update
51     begin
52       relation = Relation.find(params[:id])
53
54       if relation.visible
55         new_relation = Relation.from_xml(request.raw_post)
56
57         if new_relation and new_relation.id == relation.id
58           if !new_relation.preconditions_ok?
59             render :nothing => true, :status => :precondition_failed
60           else
61             relation.user_id = @user.id
62             relation.tags = new_relation.tags
63             relation.members = new_relation.members
64             relation.visible = true
65
66             if relation.save_with_history
67               render :nothing => true
68             else
69               render :nothing => true, :status => :internal_server_error
70             end
71           end
72         else
73           render :nothing => true, :status => :bad_request
74         end
75       else
76         render :nothing => true, :status => :gone
77       end
78     rescue ActiveRecord::RecordNotFound
79       render :nothing => true, :status => :not_found
80     rescue
81       render :nothing => true, :status => :internal_server_error
82     end
83   end
84
85   def delete
86 #XXX check if member somewhere!
87     begin
88       relation = Relation.find(params[:id])
89
90       if relation.visible
91         if RelationMember.find(:first, :joins => "INNER JOIN current_relations ON current_relations.id=current_relation_members.id", :conditions => [ "visible = 1 AND member_type='relation' and member_id=?", params[:id]])
92           render :nothing => true, :status => :precondition_failed
93         else
94           relation.user_id = @user.id
95           relation.tags = []
96           relation.members = []
97           relation.visible = false
98
99           if relation.save_with_history
100             render :nothing => true
101           else
102             render :nothing => true, :status => :internal_server_error
103           end
104         end
105       else
106         render :nothing => true, :status => :gone
107       end
108     rescue ActiveRecord::RecordNotFound
109       render :nothing => true, :status => :not_found
110     rescue
111       render :nothing => true, :status => :internal_server_error
112     end
113   end
114
115   def full
116     begin
117       relation = Relation.find(params[:id])
118
119       if relation.visible
120         # In future, we might want to do all the data fetch in one step
121         seg_ids = relation.segs + [-1]
122         segments = Segment.find_by_sql "select * from current_segments where visible = 1 and id IN (#{seg_ids.join(',')})"
123
124         node_ids = segments.collect {|segment| segment.node_a }
125         node_ids += segments.collect {|segment| segment.node_b }
126         node_ids += [-1]
127         nodes = Node.find(:all, :conditions => "visible = 1 AND id IN (#{node_ids.join(',')})")
128
129         # Render
130         doc = OSM::API.new.get_xml_doc
131         nodes.each do |node|
132           doc.root << node.to_xml_node()
133         end
134         segments.each do |segment|
135           doc.root << segment.to_xml_node()
136         end
137         doc.root << relation.to_xml_node()
138
139         render :text => doc.to_s, :content_type => "text/xml"
140       else
141         render :nothing => true, :status => :gone
142       end
143     rescue ActiveRecord::RecordNotFound
144       render :nothing => true, :status => :not_found
145     rescue
146       render :nothing => true, :status => :internal_server_error
147     end
148   end
149
150   def relations
151     ids = params['relations'].split(',').collect { |w| w.to_i }
152
153     if ids.length > 0
154       doc = OSM::API.new.get_xml_doc
155
156       Relation.find(ids).each do |relation|
157         doc.root << relation.to_xml_node
158       end
159
160       render :text => doc.to_s, :content_type => "text/xml"
161     else
162       render :nothing => true, :status => :bad_request
163     end
164   end
165
166   def relations_for_object(objtype)
167     relationids = RelationMember.find(:all, :conditions => ['member_type=? and member_id=?', objtype, params[:id]]).collect { |ws| ws.id }.uniq
168
169     if relationids.length > 0
170       doc = OSM::API.new.get_xml_doc
171
172       Relation.find(relationids).each do |relation|
173         doc.root << relation.to_xml_node
174       end
175
176       render :text => doc.to_s, :content_type => "text/xml"
177     else
178       render :nothing => true, :status => :bad_request
179     end
180   end
181 end