Initial support for searching
[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"] = 'application/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