X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/ea1961e3ce54432e15a2468fb7b711937fd1517a..233a97bfcbee9c82027c049bb8bafac2693ec359:/app/controllers/changeset_controller.rb?ds=sidebyside diff --git a/app/controllers/changeset_controller.rb b/app/controllers/changeset_controller.rb index db3a26295..8151d3a67 100644 --- a/app/controllers/changeset_controller.rb +++ b/app/controllers/changeset_controller.rb @@ -57,13 +57,13 @@ class ChangesetController < ApplicationController def close begin - if not request.put? + unless request.put? render :nothing => true, :status => :method_not_allowed return end changeset = Changeset.find(params[:id]) changeset.open = false - changeset.save + changeset.save! render :nothing => true rescue ActiveRecord::RecordNotFound render :nothing => true, :status => :not_found @@ -71,24 +71,25 @@ class ChangesetController < ApplicationController end def upload - if not request.put? + unless request.put? render :nothing => true, :status => :method_not_allowed return end - # FIXME: this should really be done without loading the whole XML file - # into memory. - p = XML::Parser.new - p.string = request.raw_post - doc = p.parse + p = XML::Reader.new request.raw_post node_ids, way_ids, rel_ids = {}, {}, {} ids = {"node"=>node_ids, "way"=>way_ids, "relation"=>rel_ids} + models = {"node"=>Node, "way"=>Way, "relation"=>Relation} + + # FIXME shouldn't this be done through the + # res = OSM::API.new.get_xml_doc + # as everything else is? res = XML::Document.new res.encoding = 'UTF-8' root = XML::Node.new 'osm' - root['version'] = '0.6' + root['version'] = API_VERSION root['creator'] = 'OpenStreetMap.org' res.root = root @@ -96,93 +97,76 @@ class ChangesetController < ApplicationController "not a normal OSM file. ") Changeset.transaction do - doc.find('//osm/create/node').each do |nd| - elem = XML::Node.new 'node' - node = Node.from_xml_node(nd, true) - elem['old_id'] = nd['id'] - create_prim node_ids, node, nd - elem['new_id'] = node.id.to_s - elem['new_version'] = node.version.to_s - root << elem - end - doc.find('//osm/create/way').each do |nd| - elem = XML::Node.new 'way' - way = Way.from_xml_node(nd, true) - elem['old_id'] = nd['id'] - fix_way(way, node_ids) - raise OSM::APIPreconditionFailedError.new if !way.preconditions_ok? - create_prim way_ids, way, nd - elem['new_id'] = way.id.to_s - elem['new_version'] = way.version.to_s - root << elem - end - doc.find('//osm/create/relation').each do |nd| - elem = XML::Node.new 'relation' - relation = Relation.from_xml_node(nd, true) - elem['old_id'] = nd['id'] - fix_rel(relation, ids) - raise OSM::APIPreconditionFailedError.new if !relation.preconditions_ok? - create_prim rel_ids, relation, nd - elem['new_id'] = relation.id.to_s - elem['new_version'] = relation.version.to_s - root << elem - end - - doc.find('//osm/modify/relation').each do |nd| - elem = XML::Node.new 'relation' - new_relation = Relation.from_xml_node(nd) - relation = Relation.find(new_relation.id) - relation.update_from new_relation, @user - elem['old_id'] = elem['new_id'] = relation.id.to_s - elem['new_version'] = relation.version.to_s - root << elem - end - doc.find('//osm/modify/way').each do |nd| - elem = XML::Node.new 'way' - new_way = Way.from_xml_node(nd) - way = Way.find(new_way.id) - way.update_from new_way, @user - elem['old_id'] = elem['new_id'] = way.id.to_s - elem['new_version'] = way.version.to_s - root << elem - end - doc.find('//osm/modify/node').each do |nd| - elem = XML::Node.new 'node' - new_node = Node.from_xml_node(nd) - node = Node.find(new_node.id) - node.update_from new_node, @user - elem['old_id'] = elem['new_id'] = node.id.to_s - elem['new_version'] = node.version.to_s - root << elem - end - - doc.find('//osm/delete/relation').each do |nd| - elem = XML::Node.new 'relation' - relation = Relation.find(nd['id']) - relation.delete_with_history(@user) - elem['old_id'] = elem['new_id'] = relation.id.to_s - elem['new_version'] = relation.version.to_s - root << elem - end - doc.find('//osm/delete/way').each do |nd| - elem = XML::Node.new 'way' - way = Way.find(nd['id']) - way.delete_with_history(@user) - elem['old_id'] = elem['new_id'] = way.id.to_s - elem['new_version'] = way.version.to_s - root << elem - end - doc.find('//osm/delete/node').each do |nd| - elem = XML::Node.new 'node' - new_node = Node.from_xml_node(nd) - node = Node.find(nd['id']) - node.delete_with_history(@user) - elem['old_id'] = elem['new_id'] = node.id.to_s - elem['new_version'] = node.version.to_s - root << elem + while p.read == 1 + break if p.node_type == 15 # end element + next unless p.node_type == 1 # element + + case p.name + when 'create': + while p.read == 1 + break if p.node_type == 15 # end element + next unless p.node_type == 1 # element + + model = models[p.name] + next if model.nil? + + elem = XML::Node.new p.name + nd = p.expand; p.next + osm = model.from_xml_node(nd, true) + elem['old_id'] = nd['id'] + + case nd.name + when 'way': + fix_way(osm, node_ids) + raise OSM::APIPreconditionFailedError.new if !osm.preconditions_ok? + when 'relation': + fix_rel(osm, ids) + raise OSM::APIPreconditionFailedError.new if !osm.preconditions_ok? + end + + create_prim ids[nd.name], osm, nd + elem['new_id'] = osm.id.to_s + elem['new_version'] = osm.version.to_s + root << elem + end + when 'modify': + while p.read == 1 + break if p.node_type == 15 # end element + next unless p.node_type == 1 # element + + model = models[p.name] + next if model.nil? + + elem = XML::Node.new p.name + new_osm = model.from_xml_node(p.expand); p.next + osm = model.find(new_osm.id) + osm.update_from new_osm, @user + elem['old_id'] = elem['new_id'] = osm.id.to_s + elem['new_version'] = osm.version.to_s + root << elem + end + when 'delete': + while p.read == 1 + break if p.node_type == 15 # end element + next unless p.node_type == 1 # element + + model = models[p.name] + next if model.nil? + + elem = XML::Node.new p.name + osm = model.find(p.expand['id']); p.next + osm.delete_with_history(@user) + elem['old_id'] = elem['new_id'] = osm.id.to_s + elem['new_version'] = osm.version.to_s + root << elem + end + end end end render :text => res.to_s, :content_type => "text/xml" + + rescue OSM::APIError => ex + render ex.render_opts end end