updates from hacking day
[rails.git] / app / models / way.rb
1 class Way < ActiveRecord::Base
2   require 'xml/libxml'
3   
4   belongs_to :user
5
6   has_many :way_segments, :foreign_key => 'id'
7   has_many :way_tags, :foreign_key => 'id'
8
9   has_many :old_ways, :foreign_key => :id
10
11   set_table_name 'current_ways'
12
13   def self.from_xml(xml, create=false)
14     p = XML::Parser.new
15     p.string = xml
16     doc = p.parse
17
18     way = Way.new
19
20     doc.find('//osm/way').each do |pt|
21       if !create and pt['id'] != '0'
22         way.id = pt['id'].to_i
23       end
24
25       if create
26         way.timestamp = Time.now
27         way.visible = true
28       else
29         if pt['timestamp']
30           way.timestamp = Time.parse(pt['timestamp'])
31         end
32       end
33
34       pt.find('tag').each do |tag|
35         way.add_tag_keyval(tag['k'], tag['v'])
36       end
37
38       pt.find('seg').each do |seg|
39         way.add_seg_num(seg['id'])
40       end
41
42     end
43
44     return way
45   end
46
47   def to_xml
48     doc = OSM::API.new.get_xml_doc
49     doc.root << to_xml_node()
50     return doc
51   end
52
53   def to_xml_node(visible_segments = nil, user_display_name_cache = nil)
54     el1 = XML::Node.new 'way'
55     el1['id'] = self.id.to_s
56     el1['visible'] = self.visible.to_s
57     el1['timestamp'] = self.timestamp.xmlschema
58
59     if user_display_name_cache and user_display_name_cache[self.user_id]
60       # use the cache if available
61     else
62       user_display_name_cache[self.user_id] = self.user.display_name
63     end
64     
65     #el1['user'] = self.user.display_name if self.user.data_public?
66     el1['user'] = user_display_name_cache[self.user_id]
67
68     # make sure segments are output in sequence_id order
69     ordered_segments = []
70     self.way_segments.each do |seg|
71       if visible_segments
72         # if there is a list of visible segments then use that to weed out deleted segments
73         if visible_segments[seg.segment_id]
74           ordered_segments[seg.sequence_id] = seg.segment_id.to_s
75         end
76       else
77         # otherwise, manually go to the db to check things
78         if seg.segment.visible? and seg.segment.from_node.visible? and seg.segment.to_node.visible?
79           ordered_segments[seg.sequence_id] = seg.segment_id.to_s
80         end
81       end
82     end
83
84     ordered_segments.each do |seg_id|
85       if seg_id
86         e = XML::Node.new 'seg'
87         e['id'] = seg_id
88         el1 << e
89       end
90     end
91  
92     self.way_tags.each do |tag|
93       e = XML::Node.new 'tag'
94       e['k'] = tag.k
95       e['v'] = tag.v
96       el1 << e
97     end
98     return el1
99   end 
100
101   def segs
102     unless @segs
103         @segs = Array.new
104         self.way_segments.each do |seg|
105             @segs += [seg.segment_id]
106         end
107     end
108     @segs
109   end
110
111   def tags
112     unless @tags
113         @tags = Hash.new
114         self.way_tags.each do |tag|
115             @tags[tag.k] = tag.v
116         end
117     end
118     @tags
119   end
120
121   def segs=(s)
122     @segs = s
123   end
124
125   def tags=(t)
126     @tags = t
127   end
128
129   def add_seg_num(n)
130     @segs = Array.new unless @segs
131     @segs << n.to_i
132   end
133
134   def add_tag_keyval(k, v)
135     @tags = Hash.new unless @tags
136     @tags[k] = v
137   end
138
139   def save_with_history
140     t = Time.now
141     self.timestamp = t
142     self.save
143     
144     WayTag.delete_all(['id = ?', self.id])
145
146     self.tags.each do |k,v|
147       tag = WayTag.new
148       tag.k = k
149       tag.v = v
150       tag.id = self.id
151       tag.save
152     end
153
154     WaySegment.delete_all(['id = ?', self.id])
155     
156     i = 0
157     self.segs.each do |n|
158       seg = WaySegment.new
159       seg.id = self.id
160       seg.segment_id = n
161       seg.sequence_id = i
162       seg.save
163       i += 1
164     end
165
166     old_way = OldWay.from_way(self)
167     old_way.timestamp = t
168     old_way.save_with_dependencies
169   end
170
171   def preconditions_ok?
172     self.segs.each do |n|
173       segment = Segment.find(n)
174       unless segment and segment.visible and segment.preconditions_ok?
175         return false
176       end
177     end
178     return true
179   end
180
181 end