require 'facets/symbol/to_proc'
module Webgen
# Stores the configuration for a webgen website.
#
# Configuration options should be created like this:
#
# config.my.new.config 'value', :doc => 'some', :meta => 'info'
#
# and later accessed or set using the accessor methods #[] and #[]= or a configuration
# helper. These helpers are defined in the Helpers module and provide easier access to complex
# configuration options.
class Configuration
# Helper class for providing an easy method to define configuration options.
class MethodChain
def initialize(config) #:nodoc:
@config = config
@name = ''
end
def method_missing(id, *args) #:nodoc:
@name += (@name.empty? ? '' : '.') + id.id2name.sub(/(!|=)$/,'')
if args.length > 0
value = args.shift
@config.data[@name] = value unless @config.data.has_key?(@name) # value is set only the first time
@config.meta_info[@name] ||= {}
@config.meta_info[@name].update(*args) if args.length > 0
nil
else
self
end
end
end
# This module provides methods for setting more complex configuration options. It is mixed into
# Webgen::Configuration so that its methods can be used. Detailed information on the use of the
# methods can be found in the "User Manual" in the "Configuration File" section.
#
# All public methods defined in this module are available for direct use in the
# configuration file, e.g. the method named +default_meta_info+ can be used like this:
#
# default_meta_info:
# Webgen::SourceHandler::Page:
# in_menu : true
# :action : replace
#
# All methods have to take exactly one argument, a Hash.
#
# The special key :action should be used for specifying how the configuration option
# should be set:
#
# replace:: Replace the configuration option with the new values.
# modify:: Replace old values with new values and add missing ones (useful for hashes and
# normally the default value)
module Helpers
# Set the default meta information for source handlers.
def default_meta_info(args)
args.each do |sh_name, mi|
raise ArgumentError, 'Invalid argument for configuration helper default_meta_info' unless mi.kind_of?(Hash)
action = mi.delete(:action) || 'modify'
mi_hash = (self['sourcehandler.default_meta_info'][complete_source_handler_name(sh_name)] ||= {})
case action
when 'replace' then mi_hash.replace(mi)
else mi_hash.update(mi)
end
end
end
# Set the path patterns used by source handlers.
def patterns(args)
args.each do |sh_name, data|
pattern_arr = (self['sourcehandler.patterns'][complete_source_handler_name(sh_name)] ||= [])
case data
when Array then pattern_arr.replace(data)
when Hash
(data['del'] || []).each {|pat| pattern_arr.delete(pat)}
(data['add'] || []).each {|pat| pattern_arr << pat}
else
raise ArgumentError, 'Invalid argument for configuration helper patterns'
end
end
end
# Set the default processing pipeline for a source handler.
def default_processing_pipeline(args)
args.each do |sh_name, pipeline|
raise ArgumentError, 'Invalid argument for configuration helper pipeline' unless pipeline.kind_of?(String)
mi_hash = (self['sourcehandler.default_meta_info'][complete_source_handler_name(sh_name)] ||= {})
((mi_hash['blocks'] ||= {})['default'] ||= {})['pipeline'] = pipeline
end
end
# Complete +sh_name+ by checking if a source handler called
# Webgen::SourceHandler::SH_NAME exists.
def complete_source_handler_name(sh_name)
(Webgen::SourceHandler.constants.map(&:to_s).include?(sh_name) ? 'Webgen::SourceHandler::' + sh_name : sh_name)
end
private :complete_source_handler_name
end
include Helpers
# The hash which stores the meta info for the configuration options.
attr_reader :meta_info
# The configuration options hash.
attr_reader :data
# Create a new Configuration object.
def initialize
@data = {}
@meta_info = {}
end
# Return the configuration option +name+.
def [](name)
if @data.has_key?(name)
@data[name]
else
raise ArgumentError, "No such configuration option: #{name}"
end
end
# Set the configuration option +name+ to the provided +value+.
def []=(name, value)
if @data.has_key?(name)
@data[name] = value
else
raise ArgumentError, "No such configuration option: #{name}"
end
end
def method_missing(id, *args) #:nodoc:
MethodChain.new(self).method_missing(id, *args)
end
end
end