# coding: utf-8 module Mabmapper class Engine def process(input_filename, contents, options={archive: nil}) document_class = self.class.document_class_value raise "The engine does't provide a document class. This is required." unless document_class.present? document = document_class.new(contents) fields.each do |field| begin field.send(:process, document) rescue => e puts "----------------------------" puts "Error : #{e.message}" puts "Field : #{field.name}" puts "File : #{input_filename}" puts "Archive: #{options[:archive]}" if options[:archive].present? puts "----------------------------" puts "Backtrace:" puts e.backtrace puts "----------------------------" puts end end self end def fields self.class.fields end def to_xml(only_fields = []) builder = Nokogiri::XML::Builder.new do |xml| xml.document do fields.each do |field| if field.result.present? || field.result == false next if only_fields.present? and not only_fields.include?(field.name) if field.result.is_a?(Array) #xml.send("#{field.name.downcase.pluralize}_") do field.result.each do |result| xml.send("#{field.name.downcase}_", result) end #end else xml.send("#{field.name.downcase}_", field.result) end end end end end builder.to_xml end def to_hash hash = {} fields.each { |field| hash[field.name.downcase] = field.result } hash end protected class << self cattr_accessor :document_class_value cattr_accessor :fields def document_class(value) self.document_class_value = value end def field(name, &block) self.fields ||= [] self.fields << Field.new(name, &block) if block_given? end end # @see: http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation class Field def initialize(name, &block) @name = name.to_s @proc = block @engine = eval("self", block.binding) end attr_reader :name, :result, :doc def ref(field_name) field = @engine.fields.find{ |f| f.name == field_name.to_s } raise "No such field #{field_name} in section #{section_name}" if field.blank? field.result end def merge(value1, value2, options = {delimiter: ' ', wrap: nil}) v1 = [value1].map(&:presence).compact.join(options[:delimiter]) v2 = [value2].map(&:presence).compact.join(options[:delimiter]) v2 = wrap(v2, options[:wrap]) if v2.present? and options[:wrap].present? [v1, v2].map(&:presence).compact.join(options[:delimiter]) end def wrap(value, pattern) pattern.gsub("@", value) end private def process(document) @doc = document @result = instance_eval(&@proc) end end end end