p = XML::Parser.string(xml)
doc = p.parse
- cs = Changeset.new
-
doc.find('//osm/changeset').each do |pt|
- if create
- cs.created_at = Time.now.getutc
- # initial close time is 1h ahead, but will be increased on each
- # modification.
- cs.closed_at = cs.created_at + IDLE_TIMEOUT
- # initially we have no changes in a changeset
- cs.num_changes = 0
- end
-
- pt.find('tag').each do |tag|
- cs.add_tag_keyval(tag['k'], tag['v'])
- end
+ return Changeset.from_xml_node(pt, create)
end
- rescue Exception => ex
- cs = nil
+ raise OSM::APIBadXMLError.new("changeset", xml, "XML doesn't contain an osm/changeset element.")
+ rescue LibXML::XML::Error, ArgumentError => ex
+ raise OSM::APIBadXMLError.new("changeset", xml, ex.message)
+ end
+ end
+
+ def self.from_xml_node(pt, create=false)
+ cs = Changeset.new
+ if create
+ cs.created_at = Time.now.getutc
+ # initial close time is 1h ahead, but will be increased on each
+ # modification.
+ cs.closed_at = cs.created_at + IDLE_TIMEOUT
+ # initially we have no changes in a changeset
+ cs.num_changes = 0
+ else
+ raise OSM::APIBadXMLError.new("changeset", pt, "ID is required when updating.") if pt['id'].nil?
+ cs.id = pt['id'].to_i
+ # .to_i will return 0 if there is no number that can be parsed.
+ # We want to make sure that there is no id with zero anyway.
+ raise OSM::APIBadUserInput.new("ID of changeset cannot be zero when updating.") if cs.id == 0
end
+ pt.find('tag').each do |tag|
+ raise OSM::APIBadXMLError.new("changeset", pt, "tag is missing key") if tag['k'].nil?
+ raise OSM::APIBadXMLError.new("changeset", pt, "tag is missing value") if tag['v'].nil?
+ cs.add_tag_keyval(tag['k'], tag['v'])
+ end
+
return cs
end
# FIXME - this looks nasty and violates DRY... is there any prettier
# way to do this?
- @bbox[0] = [-180 * SCALE, array[0] + EXPAND * (@bbox[0] - @bbox[2])].max if array[0] < @bbox[0]
- @bbox[1] = [ -90 * SCALE, array[1] + EXPAND * (@bbox[1] - @bbox[3])].max if array[1] < @bbox[1]
- @bbox[2] = [ 180 * SCALE, array[2] + EXPAND * (@bbox[2] - @bbox[0])].min if array[2] > @bbox[2]
- @bbox[3] = [ 90 * SCALE, array[3] + EXPAND * (@bbox[3] - @bbox[1])].min if array[3] > @bbox[3]
+ @bbox[0] = [-180 * GeoRecord::SCALE, array[0] + EXPAND * (@bbox[0] - @bbox[2])].max if array[0] < @bbox[0]
+ @bbox[1] = [ -90 * GeoRecord::SCALE, array[1] + EXPAND * (@bbox[1] - @bbox[3])].max if array[1] < @bbox[1]
+ @bbox[2] = [ 180 * GeoRecord::SCALE, array[2] + EXPAND * (@bbox[2] - @bbox[0])].min if array[2] > @bbox[2]
+ @bbox[3] = [ 90 * GeoRecord::SCALE, array[3] + EXPAND * (@bbox[3] - @bbox[1])].min if array[3] > @bbox[3]
# update active record. rails 2.1's dirty handling should take care of
# whether this object needs saving or not.
def add_tag_keyval(k, v)
@tags = Hash.new unless @tags
+
+ # duplicate tags are now forbidden, so we can't allow values
+ # in the hash to be overwritten.
+ raise OSM::APIDuplicateTagsError.new("changeset", self.id, k) if @tags.include? k
+
@tags[k] = v
end