require "ev/ruby" require "ev/net" require "md5" require "thread" Same = 0 Down = 1 Up = 2 Dummy = 3 module TextArray def textarray @children.collect do |obj| [obj.text] << obj.textarray end.flatten.compact end end module ParseTree def parsetree(premethod="prechildren", postmethod="postchildren", *args) if @visible method(premethod).call(*args) if respond_to?(premethod) @children.each do |obj| obj.parsetree(premethod, postmethod, *args) end method(postmethod).call(*args) if respond_to?(postmethod) end end #def parsetree(premethod="prechildren", postmethod="postchildren", *args) # stack = [self] # done = [] # # while not stack.empty? # obj = stack.pop # # if not done.include?(obj) # obj.method(premethod).call(*args) if obj.respond_to?(premethod) # # stack.push(obj) # done.push(obj) # # stack.concat obj.children.reverse # #obj.children.reverse.each do |cobj| # #stack.push(cobj) # #end # else # obj.method(postmethod).call(*args) if obj.respond_to?(postmethod) # end # end #end end class TreeObject attr_reader :subtype attr_writer :subtype attr_reader :upordown attr_writer :upordown attr_reader :level attr_writer :level attr_reader :parent attr_writer :parent attr_reader :children attr_writer :children attr_reader :closed attr_writer :closed attr_reader :text attr_writer :text attr_reader :visible attr_writer :visible include TextArray include ParseTree def initialize(subtype=nil) @subtype = subtype @upordown = Same @level = nil @parent = nil @children = [] @closed = nil @visible = true end def inspect parent, children = @parent, @children @parent, @children = parent.id, children.collect{|obj| obj.id} res = " " * (level-1) + "#{self.class}(#{@subtype}) #{super}" @parent, @children = parent, children res end end class Tree @@versie = 1 @@mutex = Mutex.new attr_reader :data attr_writer :data attr_reader :parent attr_writer :parent attr_reader :children attr_writer :children attr_reader :visible attr_writer :visible include TextArray include ParseTree def initialize(string) string = string.join("") if string.kind_of?(Array) @data = string @parent = nil @children = [] @objects = [] @visible = true @checkvisibility = false buildobjects(string) buildparents buildchildren markclosed deletedummies @checkvisibility = true end def self.file(file) new(File.new(file).readlines) end def self.location(url, form=Hash.new) s = HTTPClient.get(url, form) s = "" if s.nil? new(s) end def self.new_from_cache2(data) new(data) end def self.new_from_cache(data) hash = MD5.new("#{@@versie} #{data}") dir = "#{temp}/evcache.#{user}/tree.new" file = "#{dir}/#{hash}" tree = nil Dir.mkdirrec(dir) if File.file?(file) @@mutex.synchronize do tree = Marshal.restore(File.new(file, "rb")) end else tree = new(data) if not tree.nil? @@mutex.synchronize do File.open(file, "wb") {|f| Marshal.dump(tree, f)} end end end return tree end def inspect @objects.collect do |obj| obj.inspect end.join("\n") end def buildobjects(string) raise "Has to be defined in the subclass." end def buildparents level = 1 levels = Hash.new levels[0] = nil parse do |type, obj| case obj.upordown when Down obj.level = level obj.parent = levels[level-1] levels[level] = obj level += 1 when Up, Dummy pl = level 1.upto(level-1) do |l| po = levels[l] pl = l if po.subtype == obj.subtype end level = pl obj.level = level obj.parent = levels[level-1] when Same obj.level = level obj.parent = levels[level-1] end end end def buildchildren @objects.each do |obj| obj.children = [] end parse do |type, obj| if not obj.parent.nil? po = obj.parent po.children << obj else @children << obj end end end def markclosed ([self].concat @objects).each do |obj| obj.children.each_index do |i| co1 = obj.children[i] co2 = obj.children[i+1] co1.closed = (not co2.nil? and co1.upordown == Down and (co2.upordown == Up or co2.upordown == Dummy) and co1.subtype == co2.subtype) end end end def deletedummies ([self].concat @objects).each do |obj| obj.children.delete_if do |obj2| obj2.upordown == Dummy end end @objects.delete_if do |obj| obj.upordown == Dummy end end def parse(types=[], subtypes=[], once=false) types = [types] if types.class == Class subtypes = [subtypes] if subtypes.class == String hidelevel = nil catch :once do @objects.each do |obj| if (@checkvisibility and hidelevel.nil? and (not obj.visible)) hidelevel = obj.level else if (@checkvisibility and (not hidelevel.nil?) and obj.visible and obj.level <= hidelevel) hidelevel = nil end end if hidelevel.nil? ok = false catch :stop do if types.empty? if subtypes.empty? ok = true throw :stop else subtypes.each do |st| if obj.subtype == st ok = true throw :stop end end end else if subtypes.empty? types.each do |t| if obj.kind_of?(t) ok = true throw :stop end end else types.each do |t| subtypes.each do |st| if obj.kind_of?(t) and obj.subtype == st ok = true throw :stop end end end end end end if ok yield(obj.class.to_s, obj) throw :once if once end end end end end def path(pad) p1 = self unless pad.nil? pad.split(/\//).each do |deel| tag, voorkomen = deel.split(/:/) if (not tag.nil?) and (not p1.nil?) voorkomen = 1 if voorkomen.nil? voorkomen = voorkomen.to_i teller = 0 p2 = nil p1.children.each_index do |i| #if p1.children[i].upordown == Down unless p1.children[i].subtype.nil? if p1.children[i].subtype.noquotes == tag.noquotes teller += 1 p2 = p1.children[i] if teller == voorkomen end end #end end p1 = p2 end end end p1 end end