$:.unshift File.dirname(__FILE__) require 'template_exception' module BuildMaster class TemplateRunner @@NAMESPACE = 'http://buildmaster.rubyforge.org/xtemplate/1.0' attr_reader :templatelets attr_writer :templatelets def initialize(target, template, source, &evaluator) @templatelets = Hash.new @target = target @template = template @source_instance = source @templatelets = templatelets @evaluator = evaluator end def process process_children(@target, @template) end private def process_children(target, template) template.each do |element| if (element.kind_of? REXML::Element) process_element(target, element) else target.add(deep_clone(element)) end end end def process_element(target, element) if (template_directive?(element)) process_directive(target, element) else output_element = clone_element(element) target.add(output_element) process_children(output_element, element) end end def template_directive?(element) element.namespace == @@NAMESPACE end def process_directive(target, template_element) message = "process_#{template_element.name}_directive" templatelet = @templatelets[template_element.name] if (not templatelet) raise TemplateException, "unable to process element template:#{template_element.name}" end templatelet.process(target, template_element, @source_instance) end def clone_element( template_element ) cloned_element = REXML::Element.new( template_element.expanded_name ) copy_attributes( template_element, cloned_element ) cloned_element end def copy_attributes( template_element, expanded_element ) template_element.attributes.each_attribute do |attribute| expanded_element.attributes.add( attribute.clone ) end end def deep_clone( node ) if node.kind_of? REXML::Parent node.deep_clone else node.clone end end end end