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