require "rexml/parsers/baseparser"
require "rexml/parsers/streamparser"
require "rexml/streamlistener"
include REXML

class ListenerAdapter
  include StreamListener
  
  def initialize(metricId, collector, listeners = {"MetricDescriptions" => :FullListener, "Cycle" => :FlatListener})
    super()
    @metricId = metricId
    @collector = collector
    @listeners = listeners
    @strategy = nil
  end
  
  def tag_start(name, attributes)
    @strategy.tag_start(name, attributes) unless @strategy.nil?
  end
  
  def tag_end(name)
    if @strategy.nil?
      if @listeners.has_key? name
        @strategy = Object.const_get(@listeners[name]).new(@metricId, @collector)
      end
    else
      @strategy.tag_end(name)
    end
  end
end

class FullListener
  def initialize(metricId, collector)
    @metricId = metricId
    @collector = collector
    @inType = nil
    @inPackage = nil
    @inMethod = false
  end
  
  def tag_start(name, attributes)
    if name == "Type"
      @inType = attributes["handle"]
    elsif name == "Package"
      @inPackage = attributes["handle"]
    elsif name == "Method"
      @inMethod = true
    elsif name == "Metric" && attributes["id"] == @metricId
      if !@inMethod && @inType != nil
        @collector.new_metric(@inType, attributes["value"].tr(',','.').to_f)
      elsif @inPackage != nil && attributes["per"].nil?
        @collector.new_metric(@inPackage, attributes["value"].tr(',','.').to_f)
      end
    end
  end
  
  def tag_end(name)
    if name == "Type"
      @inType = nil
    elsif name == "Package"
      @inPackage = nil
    elsif name == "Method"
      @inMethod = false
    end
  end
end

class FlatListener
  def initialize(metricId, collector)
    @metricId = metricId
    @collector = collector
    @inMetric = false
    @perMethod = false
    @perPackage = false
  end
  
  def tag_start(name, attributes)
    if name == "Metric" && attributes["id"] == @metricId
      @inMetric = true
    elsif name == "Values" && @inMetric
      if attributes["per"] == "method"
        @perMethod = true
      elsif attributes["per"] == "packageFragment"
        @perPackage = true
      end
    elsif name == "Value" && @inMetric
      type = "#{attributes['package']}.#{attributes['source']}"
      if @perMethod
        @collector.add_metric(type, attributes["value"].tr(',','.').to_f)
      elsif @perPackage
        @collector.new_metric(attributes['package'], attributes["value"].tr(',','.').to_f)
      else
        @collector.new_metric(type, attributes["value"].tr(',','.').to_f)
      end
    end
  end
  
  def tag_end(name)
    if name == "Metric"
      @inMetric = false
    elsif name == "Values"
      @perMethod = false
      @perPackage = false
    end
  end
end
