lib/coopy/alignment.rb
module Coopy
class Alignment
attr_accessor :reference # Alignment
attr_accessor :meta # Alignment
def initialize
@map_a2b = {} # Map<Int,Int>
@map_b2a = {} # Map<Int,Int>
@ha = @hb = 0
@map_count = 0
@reference = nil
@meta = nil
@order_cache_has_reference = false
@ia = 0
@ib = 0
end
def range(ha, hb)
@ha = ha
@hb = hb
end
def tables(ta, tb)
@ta = ta
@tb = tb
end
def headers(ia, ib)
@ia = ia
@ib = ib
end
def set_rowlike(flag)
end
def hb
@hb
end
def link(a, b)
@map_a2b[a] = b
@map_b2a[b] = a
@map_count+=1
end
def add_index_columns(unit)
if @index_columns.nil?
@index_columns = []
end
@index_columns << unit
end
def get_index_columns
@index_columns
end
def a2b(a)
@map_a2b[a]
end
def b2a(b)
@map_b2a[b]
end
def count
@map_count
end
def to_s
map_a2b.to_s
end
def to_order
if @order_cache
if @reference
if !@order_cache_has_reference
@order_cache = nil
end
end
end
@order_cache = to_order_3 if @order_cache.nil?
@order_cache_has_reference = true if reference
@order_cache
end
def get_source
@ta
end
def get_target
@tb
end
def get_source_header
@ia
end
def get_target_header
@ib
end
def to_order_3
ref = @reference
if ref.nil?
ref = Coopy::Alignment.new
ref.range(@ha,@ha)
ref.tables(@ta,@ta)
(0...@ha).each do |i|
ref.link(i,i)
end
end
order = Coopy::Ordering.new
if @reference.nil?
order.ignore_parent
end
xp = 0
xl = 0
xr = 0
hp = @ha
hl = ref.hb
hr = @hb
vp = {}
vl = {}
vr = {}
(0...hp).each { |i| vp[i] = i }
(0...hl).each { |i| vl[i] = i }
(0...hr).each { |i| vr[i] = i }
ct_vp = hp
ct_vl = hl
ct_vr = hr
prev = -1
ct = 0
max_ct = (hp+hl+hr)*10
while (ct_vp>0 ||
ct_vl>0 ||
ct_vr>0) do
ct+=1
if ct>max_ct
puts("Ordering took too long, something went wrong")
break
end
xp = 0 if (xp>=hp)
xl = 0 if (xl>=hl)
xr = 0 if (xr>=hr)
if xp<hp && ct_vp>0
if a2b(xp).nil? && ref.a2b(xp).nil?
if vp.has_key?(xp)
order.add(-1,-1,xp)
prev = xp
vp.delete(xp)
ct_vp-=1
end
xp+=1
next
end
end
zl = nil
zr = nil
if xl<hl && ct_vl>0
zl = ref.b2a(xl)
if zl.nil?
if vl.has_key?(xl)
order.add(xl,-1,-1)
vl.delete(xl)
ct_vl-=1
end
xl+=1
next
end
end
if xr<hr && ct_vr>0
zr = b2a(xr)
if zr.nil?
if vr.has_key?(xr)
order.add(-1,xr,-1)
vr.delete(xr)
ct_vr-=1
end
xr+=1
next
end
end
if zl
if a2b(zl).nil?
# row deleted in remote
if vl.has_key?(xl)
order.add(xl,-1,zl)
prev = zl
vp.delete(zl)
ct_vp-=1
vl.delete(xl)
ct_vl-=1
xp = zl+1
end
xl+=1
next
end
end
if zr
if ref.a2b(zr).nil?
# row deleted in local
if vr.has_key?(xr)
order.add(-1,xr,zr)
prev = zr
vp.delete(zr)
ct_vp-=1
vr.delete(xr)
ct_vr-=1
xp = zr+1
end
xr+=1
next
end
end
if zl && zr && a2b(zl) && ref.a2b(zr)
# we have a choice of order
# local thinks zl should come next
# remote thinks zr should come next
if zl==prev+1 || zr!=prev+1
if vr.has_key?(xr)
order.add(ref.a2b(zr),xr,zr)
prev = zr
vp.delete(zr)
ct_vp-=1
vl.delete(ref.a2b(zr))
ct_vl-=1
vr.delete(xr)
ct_vr-=1
xp = zr+1
xl = ref.a2b(zr)+1
end
xr+=1
next
else
if vl.has_key?(xl)
order.add(xl,a2b(zl),zl)
prev = zl
vp.delete(zl)
ct_vp-=1
vl.delete(xl)
ct_vl-=1
vr.delete(a2b(zl))
ct_vr-=1
xp = zl+1
xr = a2b(zl)+1
end
xl+=1
next
end
end
xp+=1
xl+=1
xr+=1
end
return order
end
end
end