# # File:: levels.rb # Description:: Levels.xml and .dat file parser. # # Author:: David Muir # Date:: 26 November 2008 # #---------------------------------------------------------------------------- # Uses #---------------------------------------------------------------------------- require 'pipeline/os/path' require 'pipeline/util/string' require 'rexml/document' #---------------------------------------------------------------------------- # Implementation #---------------------------------------------------------------------------- module Pipeline # # == Description # The Pipeline::Levels class defines a levels.xml parser and .dat file # parser for fetching information about a level. The concept of levels was # first introduced in Jimmy. # class Levels attr_reader :project # Project reference attr_reader :branch # Branch reference attr_reader :filename # String filename of levels.xml file. attr_reader :levels # Hash of level uiname to Level objects. def initialize( project, branch, filename ) throw ArgumentError.new( "Invalid project object (#{project.class})." ) \ unless ( project.is_a?( Pipeline::Project ) ) throw ArgumentError.new( "Invalid branch object (#{branch.class})." ) \ unless ( branch.is_a?( Pipeline::Branch ) ) project.load_config( ) @project = project @branch = branch @filename = filename @levels = {} File.open( @filename ) do |fp| xmldoc = REXML::Document.new( fp ) xmldoc.elements.each( 'levels/level' ) do |xml_node| level = Level::from_xml( xml_node, self ) throw RuntimeError.new( "Duplicate level data, key #{level.uiname} already used." ) \ if ( @levels.has_key?( level.uiname ) ) @levels[level.uiname] = level end end end end # # == Description # The Pipeline::Level class defines data read from the levels.xml file and # the .dat file - essentially a mapping of file type to a filename. # # The filenames returned have environment values ready for substitution. # class Level attr_reader :levels # Reference to owning Levels object. attr_reader :uiname # Level friendlyname attr_reader :title # Level title string attr_reader :dat_filename # String filename of .dat file. attr_reader :dat # Hash of file type String keys to filenames def initialize( levels, uiname, title, dat_filename ) @levels = levels @uiname = uiname @title = title @levels.branch.in_env do |env| @dat_filename = env.subst( dat_filename ) end @dat = {} parse_dat( ) end # # Create a Level object from an XML node. # def Level::from_xml( xml_node, levels ) uiname = xml_node.attributes['friendlyName'] title = xml_node.attributes['title'] filename = xml_node.attributes['filename'] filename.gsub!( 'common:', '$(common)' ) Level.new( levels, uiname, title, filename ) end #-------------------------------------------------------------------------- # Private Methods #-------------------------------------------------------------------------- private def parse_dat( ) dat_data = [] File::open( @dat_filename ) do |fp| dat_data = fp.readlines( ) end dat_data.each do |line| # Ignore comments and empty lines line.strip! next if ( 0 == line.size ) next if ( line.starts_with( '#' ) ) # Replace common: and platform: with our environment tokens. line_dup = line.dup line_dup.gsub!( /common:/i, '$(common)' ) line_dup.gsub!( /platform:/i, '$(platform)' ) @levels.branch.in_env do |env| parts = line_dup.split( ' ' ) key = parts[0].upcase file = env.subst( OS::Path::normalise( parts[1] ) ) @dat[key] = [] unless ( @dat.has_key?( key ) ) @dat[key] << file end end end end end # levels.rb