preliminary commit 0.5 API with relations / untested after entity-relation rename, some changes still in queue
This commit is contained in:
parent
02451061ce
commit
78b440ffc1
46 changed files with 1841 additions and 231 deletions
111
app/models/old_relation.rb
Normal file
111
app/models/old_relation.rb
Normal file
|
@ -0,0 +1,111 @@
|
|||
class OldRelation < ActiveRecord::Base
|
||||
set_table_name 'relations'
|
||||
|
||||
belongs_to :user
|
||||
|
||||
def self.from_relation(relation)
|
||||
old_relation = OldRelation.new
|
||||
old_relation.visible = relation.visible
|
||||
old_relation.user_id = relation.user_id
|
||||
old_relation.timestamp = relation.timestamp
|
||||
old_relation.id = relation.id
|
||||
old_relation.members = relation.members
|
||||
old_relation.tags = relation.tags
|
||||
return old_relation
|
||||
end
|
||||
|
||||
def save_with_dependencies!
|
||||
|
||||
# see comment in old_way.rb ;-)
|
||||
save!
|
||||
clear_aggregation_cache
|
||||
clear_association_cache
|
||||
@attributes.update(OldRelation.find(:first, :conditions => ['id = ? AND timestamp = ?', self.id, self.timestamp]).instance_variable_get('@attributes'))
|
||||
|
||||
# ok, you can touch from here on
|
||||
|
||||
self.tags.each do |k,v|
|
||||
tag = OldRelationTag.new
|
||||
tag.k = k
|
||||
tag.v = v
|
||||
tag.id = self.id
|
||||
tag.version = self.version
|
||||
tag.save!
|
||||
end
|
||||
|
||||
i = 1
|
||||
self.members.each do |m|
|
||||
member = OldRelationMember.new
|
||||
member.id = self.id
|
||||
member.member_type = m[0]
|
||||
member.member_id = m[1]
|
||||
member.member_role = m[2]
|
||||
member.version = self.version
|
||||
member.save!
|
||||
end
|
||||
end
|
||||
|
||||
def members
|
||||
unless @members
|
||||
@members = Array.new
|
||||
OldRelationMember.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version]).each do |m|
|
||||
@members += [[m.type,m.id,m.role]]
|
||||
end
|
||||
end
|
||||
@members
|
||||
end
|
||||
|
||||
def tags
|
||||
unless @tags
|
||||
@tags = Hash.new
|
||||
OldRelationTag.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version]).each do |tag|
|
||||
@tags[tag.k] = tag.v
|
||||
end
|
||||
end
|
||||
@tags = Hash.new unless @tags
|
||||
@tags
|
||||
end
|
||||
|
||||
def members=(s)
|
||||
@members = s
|
||||
end
|
||||
|
||||
def tags=(t)
|
||||
@tags = t
|
||||
end
|
||||
|
||||
# has_many :relation_segments, :class_name => 'OldRelationSegment', :foreign_key => 'id'
|
||||
# has_many :relation_tags, :class_name => 'OldRelationTag', :foreign_key => 'id'
|
||||
|
||||
def old_members
|
||||
OldRelationMember.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
|
||||
end
|
||||
|
||||
def old_tags
|
||||
OldRelationTag.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
|
||||
end
|
||||
|
||||
def to_xml_node
|
||||
el1 = XML::Node.new 'relation'
|
||||
el1['id'] = self.id.to_s
|
||||
el1['visible'] = self.visible.to_s
|
||||
el1['timestamp'] = self.timestamp.xmlschema
|
||||
el1['user'] = self.user.display_name if self.user.data_public?
|
||||
|
||||
self.old_members.each do |member|
|
||||
e = XML::Node.new 'member'
|
||||
e['type'] = member.member_type.to_s
|
||||
e['ref'] = member.member_id.to_s # "id" is considered uncool here as it should be unique in XML
|
||||
e['role'] = member.member_role.to_s
|
||||
el1 << e
|
||||
end
|
||||
|
||||
self.old_tags.each do |tag|
|
||||
e = XML::Node.new 'tag'
|
||||
e['k'] = tag.k
|
||||
e['v'] = tag.v
|
||||
el1 << e
|
||||
end
|
||||
return el1
|
||||
end
|
||||
end
|
6
app/models/old_relation_member.rb
Normal file
6
app/models/old_relation_member.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class OldRelationMember < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
set_table_name 'relation_members'
|
||||
|
||||
end
|
6
app/models/old_relation_tag.rb
Normal file
6
app/models/old_relation_tag.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class OldRelationTag < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
set_table_name 'relation_tags'
|
||||
|
||||
end
|
|
@ -9,7 +9,7 @@ class OldWay < ActiveRecord::Base
|
|||
old_way.user_id = way.user_id
|
||||
old_way.timestamp = way.timestamp
|
||||
old_way.id = way.id
|
||||
old_way.segs = way.segs
|
||||
old_way.nds = way.nds
|
||||
old_way.tags = way.tags
|
||||
return old_way
|
||||
end
|
||||
|
@ -39,23 +39,25 @@ class OldWay < ActiveRecord::Base
|
|||
end
|
||||
|
||||
i = 1
|
||||
self.segs.each do |n|
|
||||
seg = OldWaySegment.new
|
||||
seg.id = self.id
|
||||
seg.segment_id = n
|
||||
seg.version = self.version
|
||||
seg.save!
|
||||
self.nds.each do |n|
|
||||
nd = OldWayNode.new
|
||||
nd.id = self.id
|
||||
nd.node_id = n
|
||||
nd.sequence_id = i
|
||||
nd.version = self.version
|
||||
nd.save!
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def segs
|
||||
unless @segs
|
||||
@segs = Array.new
|
||||
OldWaySegment.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version], :order => "sequence_id").each do |seg|
|
||||
@segs += [seg.segment_id]
|
||||
def nds
|
||||
unless @nds
|
||||
@nds = Array.new
|
||||
OldWayNode.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version], :order => "sequence_id").each do |nd|
|
||||
@nds += [nd.node_id]
|
||||
end
|
||||
end
|
||||
@segs
|
||||
@nds
|
||||
end
|
||||
|
||||
def tags
|
||||
|
@ -69,19 +71,19 @@ class OldWay < ActiveRecord::Base
|
|||
@tags
|
||||
end
|
||||
|
||||
def segs=(s)
|
||||
@segs = s
|
||||
def nds=(s)
|
||||
@nds = s
|
||||
end
|
||||
|
||||
def tags=(t)
|
||||
@tags = t
|
||||
end
|
||||
|
||||
# has_many :way_segments, :class_name => 'OldWaySegment', :foreign_key => 'id'
|
||||
# has_many :way_nodes, :class_name => 'OldWayNode', :foreign_key => 'id'
|
||||
# has_many :way_tags, :class_name => 'OldWayTag', :foreign_key => 'id'
|
||||
|
||||
def old_segments
|
||||
OldWaySegment.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
|
||||
def old_nodes
|
||||
OldWayNode.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
|
||||
end
|
||||
|
||||
def old_tags
|
||||
|
@ -95,9 +97,9 @@ class OldWay < ActiveRecord::Base
|
|||
el1['timestamp'] = self.timestamp.xmlschema
|
||||
el1['user'] = self.user.display_name if self.user.data_public?
|
||||
|
||||
self.old_segments.each do |seg| # FIXME need to make sure they come back in the right order
|
||||
e = XML::Node.new 'seg'
|
||||
e['id'] = seg.segment_id.to_s
|
||||
self.old_nodes.each do |nd| # FIXME need to make sure they come back in the right order
|
||||
e = XML::Node.new 'nd'
|
||||
e['id'] = nd.node_id.to_s
|
||||
el1 << e
|
||||
end
|
||||
|
||||
|
|
6
app/models/old_way_node.rb
Normal file
6
app/models/old_way_node.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class OldWayNode < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
set_table_name 'way_nodes'
|
||||
|
||||
end
|
213
app/models/relation.rb
Normal file
213
app/models/relation.rb
Normal file
|
@ -0,0 +1,213 @@
|
|||
class Relation < ActiveRecord::Base
|
||||
require 'xml/libxml'
|
||||
|
||||
belongs_to :user
|
||||
|
||||
has_many :relation_members, :foreign_key => 'id'
|
||||
has_many :relation_tags, :foreign_key => 'id'
|
||||
|
||||
has_many :old_relations, :foreign_key => 'id', :order => 'version'
|
||||
|
||||
set_table_name 'current_relations'
|
||||
|
||||
def self.from_xml(xml, create=false)
|
||||
begin
|
||||
p = XML::Parser.new
|
||||
p.string = xml
|
||||
doc = p.parse
|
||||
|
||||
relation = Relation.new
|
||||
|
||||
doc.find('//osm/relation').each do |pt|
|
||||
if !create and pt['id'] != '0'
|
||||
relation.id = pt['id'].to_i
|
||||
end
|
||||
|
||||
if create
|
||||
relation.timestamp = Time.now
|
||||
relation.visible = true
|
||||
else
|
||||
if pt['timestamp']
|
||||
relation.timestamp = Time.parse(pt['timestamp'])
|
||||
end
|
||||
end
|
||||
|
||||
pt.find('tag').each do |tag|
|
||||
relation.add_tag_keyval(tag['k'], tag['v'])
|
||||
end
|
||||
|
||||
pt.find('member').each do |member|
|
||||
relation.add_member(member['type'], member['ref'], member['role'])
|
||||
end
|
||||
end
|
||||
rescue
|
||||
relation = nil
|
||||
end
|
||||
|
||||
return relation
|
||||
end
|
||||
|
||||
def to_xml
|
||||
doc = OSM::API.new.get_xml_doc
|
||||
doc.root << to_xml_node()
|
||||
return doc
|
||||
end
|
||||
|
||||
def to_xml_node(user_display_name_cache = nil)
|
||||
el1 = XML::Node.new 'relation'
|
||||
el1['id'] = self.id.to_s
|
||||
el1['visible'] = self.visible.to_s
|
||||
el1['timestamp'] = self.timestamp.xmlschema
|
||||
|
||||
user_display_name_cache = {} if user_display_name_cache.nil?
|
||||
|
||||
if user_display_name_cache and user_display_name_cache.key?(self.user_id)
|
||||
# use the cache if available
|
||||
elsif self.user.data_public?
|
||||
user_display_name_cache[self.user_id] = self.user.display_name
|
||||
else
|
||||
user_display_name_cache[self.user_id] = nil
|
||||
end
|
||||
|
||||
el1['user'] = user_display_name_cache[self.user_id] unless user_display_name_cache[self.user_id].nil?
|
||||
|
||||
self.relation_members.each do |member|
|
||||
p=0
|
||||
#if visible_members
|
||||
# # if there is a list of visible members then use that to weed out deleted segments
|
||||
# if visible_members[member.member_type][member.member_id]
|
||||
# p=1
|
||||
# end
|
||||
#else
|
||||
# otherwise, manually go to the db to check things
|
||||
if member.member.visible?
|
||||
p=1
|
||||
end
|
||||
#end
|
||||
if p
|
||||
e = XML::Node.new 'member'
|
||||
e['type'] = member.member_type
|
||||
e['ref'] = member.member_id.to_s
|
||||
e['role'] = member.member_role
|
||||
el1 << e
|
||||
end
|
||||
end
|
||||
|
||||
self.relation_tags.each do |tag|
|
||||
e = XML::Node.new 'tag'
|
||||
e['k'] = tag.k
|
||||
e['v'] = tag.v
|
||||
el1 << e
|
||||
end
|
||||
return el1
|
||||
end
|
||||
|
||||
# FIXME is this really needed?
|
||||
def members
|
||||
unless @members
|
||||
@members = Array.new
|
||||
self.relation_members.each do |member|
|
||||
@members += [[member.member_type,member.member_id,member.member_role]]
|
||||
end
|
||||
end
|
||||
@members
|
||||
end
|
||||
|
||||
def tags
|
||||
unless @tags
|
||||
@tags = Hash.new
|
||||
self.relation_tags.each do |tag|
|
||||
@tags[tag.k] = tag.v
|
||||
end
|
||||
end
|
||||
@tags
|
||||
end
|
||||
|
||||
def members=(m)
|
||||
@members = m
|
||||
end
|
||||
|
||||
def tags=(t)
|
||||
@tags = t
|
||||
end
|
||||
|
||||
def add_member(type,id,role)
|
||||
@members = Array.new unless @members
|
||||
@members += [[type,id,role]]
|
||||
end
|
||||
|
||||
def add_tag_keyval(k, v)
|
||||
@tags = Hash.new unless @tags
|
||||
@tags[k] = v
|
||||
end
|
||||
|
||||
def save_with_history
|
||||
begin
|
||||
Relation.transaction do
|
||||
t = Time.now
|
||||
self.timestamp = t
|
||||
self.save!
|
||||
|
||||
tags = self.tags
|
||||
|
||||
RelationTag.delete_all(['id = ?', self.id])
|
||||
|
||||
tags.each do |k,v|
|
||||
tag = RelationTag.new
|
||||
tag.k = k
|
||||
tag.v = v
|
||||
tag.id = self.id
|
||||
tag.save!
|
||||
end
|
||||
|
||||
members = self.members
|
||||
|
||||
RelationMember.delete_all(['id = ?', self.id])
|
||||
|
||||
members.each do |n|
|
||||
mem = RelationMember.new
|
||||
mem.id = self.id
|
||||
mem.member_type = n[0];
|
||||
mem.member_id = n[1];
|
||||
mem.member_role = n[2];
|
||||
mem.save!
|
||||
end
|
||||
|
||||
old_relation = OldRelation.from_relation(self)
|
||||
old_relation.timestamp = t
|
||||
old_relation.save_with_dependencies!
|
||||
end
|
||||
|
||||
return true
|
||||
rescue Exception => ex
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def preconditions_ok?
|
||||
self.members.each do |m|
|
||||
if (m[0] == "node")
|
||||
n = Node.find(:first, :conditions => ["id = ?", m[1]])
|
||||
unless n and n.visible
|
||||
return false
|
||||
end
|
||||
elsif (m[0] == "way")
|
||||
w = Way.find(:first, :conditions => ["id = ?", m[1]])
|
||||
unless w and w.visible and w.preconditions_ok?
|
||||
return false
|
||||
end
|
||||
elsif (m[0] == "relation")
|
||||
e = Relation.find(:first, :conditions => ["id = ?", m[1]])
|
||||
unless e and e.visible and e.preconditions_ok?
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
30
app/models/relation_member.rb
Normal file
30
app/models/relation_member.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
class RelationMember < ActiveRecord::Base
|
||||
set_table_name 'current_relation_members'
|
||||
|
||||
# problem with RelationMember is that it may link to any one
|
||||
# object (a node, a way, another relation), and belongs_to is
|
||||
# not flexible enough for that. So we do this, which is ugly,
|
||||
# but fortunately rails won't actually run the SQL behind that
|
||||
# unless someone really accesses .node, .way, or
|
||||
# .relation - which is what we do below based on member_type.
|
||||
# (and no: the :condition on belongs_to doesn't work here as
|
||||
# it is a condition on the *referenced* object not the
|
||||
# *referencing* object!)
|
||||
|
||||
belongs_to :node, :foreign_key => "member_id"
|
||||
belongs_to :way, :foreign_key => "member_id"
|
||||
belongs_to :relation, :foreign_key => "member_id"
|
||||
|
||||
# so we define this "member" function that returns whatever it
|
||||
# is.
|
||||
|
||||
def member()
|
||||
return (member_type == "node") ? node : (member_type == "way") ? way : relation
|
||||
end
|
||||
|
||||
# NOTE - relations are SUBJECTS of memberships. The fact that nodes,
|
||||
# ways, and relations can be the OBJECT of a membership,
|
||||
# i.e. a node/way/relation can be referenced throgh a
|
||||
# RelationMember object, is NOT modelled in rails, i.e. these links
|
||||
# have to be resolved manually, on demand.
|
||||
end
|
6
app/models/relation_tag.rb
Normal file
6
app/models/relation_tag.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class RelationTag < ActiveRecord::Base
|
||||
set_table_name 'current_relation_tags'
|
||||
|
||||
belongs_to :relation, :foreign_key => 'id'
|
||||
|
||||
end
|
|
@ -3,7 +3,7 @@ class Way < ActiveRecord::Base
|
|||
|
||||
belongs_to :user
|
||||
|
||||
has_many :way_segments, :foreign_key => 'id', :order => 'sequence_id'
|
||||
has_many :way_nodes, :foreign_key => 'id', :order => 'sequence_id'
|
||||
has_many :way_tags, :foreign_key => 'id'
|
||||
|
||||
has_many :old_ways, :foreign_key => 'id', :order => 'version'
|
||||
|
@ -36,8 +36,8 @@ class Way < ActiveRecord::Base
|
|||
way.add_tag_keyval(tag['k'], tag['v'])
|
||||
end
|
||||
|
||||
pt.find('seg').each do |seg|
|
||||
way.add_seg_num(seg['id'])
|
||||
pt.find('nd').each do |nd|
|
||||
way.add_nd_num(nd['id'])
|
||||
end
|
||||
end
|
||||
rescue
|
||||
|
@ -53,7 +53,7 @@ class Way < ActiveRecord::Base
|
|||
return doc
|
||||
end
|
||||
|
||||
def to_xml_node(visible_segments = nil, user_display_name_cache = nil)
|
||||
def to_xml_node(visible_nodes = nil, user_display_name_cache = nil)
|
||||
el1 = XML::Node.new 'way'
|
||||
el1['id'] = self.id.to_s
|
||||
el1['visible'] = self.visible.to_s
|
||||
|
@ -71,26 +71,26 @@ class Way < ActiveRecord::Base
|
|||
|
||||
el1['user'] = user_display_name_cache[self.user_id] unless user_display_name_cache[self.user_id].nil?
|
||||
|
||||
# make sure segments are output in sequence_id order
|
||||
ordered_segments = []
|
||||
self.way_segments.each do |seg|
|
||||
if visible_segments
|
||||
# if there is a list of visible segments then use that to weed out deleted segments
|
||||
if visible_segments[seg.segment_id]
|
||||
ordered_segments[seg.sequence_id] = seg.segment_id.to_s
|
||||
# make sure nodes are output in sequence_id order
|
||||
ordered_nodes = []
|
||||
self.way_nodes.each do |nd|
|
||||
if visible_nodes
|
||||
# if there is a list of visible nodes then use that to weed out deleted nodes
|
||||
if visible_nodes[nd.node_id]
|
||||
ordered_nodes[nd.sequence_id] = nd.node_id.to_s
|
||||
end
|
||||
else
|
||||
# otherwise, manually go to the db to check things
|
||||
if seg.segment.visible? and seg.segment.from_node.visible? and seg.segment.to_node.visible?
|
||||
ordered_segments[seg.sequence_id] = seg.segment_id.to_s
|
||||
if nd.node.visible? and nd.node.visible?
|
||||
ordered_nodes[nd.sequence_id] = nd.node_id.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ordered_segments.each do |seg_id|
|
||||
if seg_id and seg_id != '0'
|
||||
e = XML::Node.new 'seg'
|
||||
e['id'] = seg_id
|
||||
ordered_nodes.each do |nd_id|
|
||||
if nd_id and nd_id != '0'
|
||||
e = XML::Node.new 'nd'
|
||||
e['id'] = nd_id
|
||||
el1 << e
|
||||
end
|
||||
end
|
||||
|
@ -104,14 +104,14 @@ class Way < ActiveRecord::Base
|
|||
return el1
|
||||
end
|
||||
|
||||
def segs
|
||||
unless @segs
|
||||
@segs = Array.new
|
||||
self.way_segments.each do |seg|
|
||||
@segs += [seg.segment_id]
|
||||
def nds
|
||||
unless @nds
|
||||
@nds = Array.new
|
||||
self.way_nodes.each do |nd|
|
||||
@nds += [nd.node_id]
|
||||
end
|
||||
end
|
||||
@segs
|
||||
@nds
|
||||
end
|
||||
|
||||
def tags
|
||||
|
@ -124,17 +124,17 @@ class Way < ActiveRecord::Base
|
|||
@tags
|
||||
end
|
||||
|
||||
def segs=(s)
|
||||
@segs = s
|
||||
def nds=(s)
|
||||
@nds = s
|
||||
end
|
||||
|
||||
def tags=(t)
|
||||
@tags = t
|
||||
end
|
||||
|
||||
def add_seg_num(n)
|
||||
@segs = Array.new unless @segs
|
||||
@segs << n.to_i
|
||||
def add_nd_num(n)
|
||||
@nds = Array.new unless @nds
|
||||
@nds << n.to_i
|
||||
end
|
||||
|
||||
def add_tag_keyval(k, v)
|
||||
|
@ -161,17 +161,17 @@ class Way < ActiveRecord::Base
|
|||
tag.save!
|
||||
end
|
||||
|
||||
segs = self.segs
|
||||
nds = self.nds
|
||||
|
||||
WaySegment.delete_all(['id = ?', self.id])
|
||||
WayNode.delete_all(['id = ?', self.id])
|
||||
|
||||
i = 1
|
||||
segs.each do |n|
|
||||
seg = WaySegment.new
|
||||
seg.id = self.id
|
||||
seg.segment_id = n
|
||||
seg.sequence_id = i
|
||||
seg.save!
|
||||
nds.each do |n|
|
||||
nd = WayNode.new
|
||||
nd.id = self.id
|
||||
nd.node_id = n
|
||||
nd.sequence_id = i
|
||||
nd.save!
|
||||
i += 1
|
||||
end
|
||||
|
||||
|
@ -181,16 +181,17 @@ class Way < ActiveRecord::Base
|
|||
end
|
||||
|
||||
return true
|
||||
rescue
|
||||
rescue => ex
|
||||
puts ex
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def preconditions_ok?
|
||||
return false if self.segs.empty?
|
||||
self.segs.each do |n|
|
||||
segment = Segment.find(:first, :conditions => ["id = ?", n])
|
||||
unless segment and segment.visible and segment.preconditions_ok?
|
||||
return false if self.nds.empty?
|
||||
self.nds.each do |n|
|
||||
node = Node.find(:first, :conditions => ["id = ?", n])
|
||||
unless node and node.visible
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
5
app/models/way_node.rb
Normal file
5
app/models/way_node.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class WayNode < ActiveRecord::Base
|
||||
set_table_name 'current_way_nodes'
|
||||
|
||||
belongs_to :node
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue