f88340fb6a6c3a49f6131950e637569f77a31bc3
[rails.git] / app / controllers / search_controller.rb
1 class SearchController < ApplicationController
2   # Support searching for nodes, segments, ways, or all
3   # Can search by tag k, v, or both (type->k,value->v)
4   # Can search by name (k=name,v=....)
5
6   before_filter :authorize
7   after_filter :compress_output
8
9   def search_all
10     do_search(true,true,true)
11   end
12
13   def search_ways
14     do_search(true,false,false)
15   end
16   def search_segments
17     do_search(false,true,false)
18   end
19   def search_nodes
20     do_search(false,false,true)
21   end
22
23
24   def do_search(do_ways,do_segments,do_nodes)
25     response.headers["Content-Type"] = 'text/xml'
26
27     type = params['type']
28     value = params['value']
29     unless type or value
30       name = params['name']
31       if name
32         type = 'name'
33         value = name
34       end
35     end
36
37     way_ids = Array.new
38     ways = Array.new
39     segments = Array.new
40     nodes = Array.new
41
42     # Matching for tags table
43     cond_tbl = Array.new
44     sql = '1=1'
45     if type
46       sql += ' AND k=?'
47       cond_tbl += [type]
48     end
49     if value
50       sql += ' AND v=?'
51       cond_tbl += [value]
52     end
53     cond_tbl = [sql] + cond_tbl
54
55     # Matching for tags column
56     if type and value
57       cond_tags = ['tags LIKE ? OR tags LIKE ? OR tags LIKE ? OR tags LIKE ?', 
58       ''+type+'='+value+'',
59       ''+type+'='+value+';%',
60       '%;'+type+'='+value+';%',
61       '%;'+type+'='+value+'' ]
62     elsif type
63       cond_tags = ['tags LIKE ? OR tags LIKE ?',
64       ''+type+'=%',
65       '%;'+type+'=%' ]
66     elsif value
67       cond_tags = ['tags LIKE ? OR tags LIKE ?',
68       '%='+value+';%',
69       '%='+value+'' ]
70     else
71       cond_tags = ['1=1']
72     end
73
74
75     # First up, look for the ids of the ways we want
76     if do_ways
77       ways_tmp = WayTag.find(:all, :conditions => cond_tbl)
78       way_ids = ways_tmp.collect {|way| way.id }
79     end
80
81     # Now, segments matching
82     if do_segments
83       segs = Segment.find(:all, :conditions => cond_tags)
84     end
85
86     # Now, nodes
87     if do_nodes
88       nodes = Node.find(:all, :conditions => cond_tags)
89     end
90
91     # Get the remaining objects:
92     # Fetch the ways (until now only had their ids)
93     ways = Way.find(way_ids)
94
95     # Fetch any segments needed for our ways (only have matching segments so far)
96     seg_ids = Array.new
97     ways.each do |way|
98       seg_ids += way.segments
99     end
100     segments += Segment.find(seg_ids)
101
102     # Fetch any nodes needed for our segments (only have matching nodes so far)
103     node_ids = Array.new
104     segments.each do |seg|
105       node_ids += seg.node_a
106       node_ids += seg.node_b
107     end
108     nodes += Node.find(node_ids)
109
110
111     # Print
112     doc = OSM::API.get_xml_doc
113     nodes.each do |node|
114       doc.root << node.to_xml_node()
115     end
116
117     segments.each do |segment|
118       doc.root << segment.to_xml_node()
119     end 
120
121     ways.each do |way|
122       doc.root << way.to_xml_node()
123     end 
124
125     render :text => doc.to_s
126   end
127 end