source: subversion/sites/rails_port/app/models/way.rb @ 4144

Last change on this file since 4144 was 3796, checked in by tomhughes, 13 years ago

Handle segments which do not exist correctly and indicate that the
preconditions for the way are not met.

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