class BitGirder::Core::BitGirderClassDefinition

Constants

REQUIRED_ATTRS

Public Class Methods

code( *argv ) click to toggle source
# File lib/bitgirder/core.rb, line 797
def self.code( *argv )
    BitGirderLogger.code( *argv )
end
default_instance_mappers_for( cls ) click to toggle source
# File lib/bitgirder/core.rb, line 758
def self.default_instance_mappers_for( cls )
    
    [
        InstanceMapper.new(
            :processor => lambda { |val| val.is_a?( cls ) && val } ),

        InstanceMapper.new(
            :processor => lambda { |val|
                # Use send in case cls made it private
                val.is_a?( Hash ) && cls.send( :new, val )
            }
        )
    ]
end
for_class( cls ) click to toggle source
# File lib/bitgirder/core.rb, line 773
def self.for_class( cls )

    unless res = @@class_defs[ cls ]
 
        attrs, decl_order =
            if cls == BitGirderClass || cls == BitGirderError
                [ {}, [] ]
            else 
                cd = self.for_class( cls.superclass )
                [ Hash.new.merge( cd.attrs ), Array.new( cd.decl_order ) ]
            end
 
        @@class_defs[ cls ] = res = new(
            :cls => cls,
            :attrs => attrs,
            :attr_syms => attrs.keys.map { |id| "@#{id}".to_sym },
            :decl_order => decl_order,
            :instance_mappers => self.default_instance_mappers_for( cls )
        )
    end
 
    res
end
get_class_defs() click to toggle source
# File lib/bitgirder/core.rb, line 736
def self.get_class_defs
    @@class_defs.dup
end
get_validation_listener() click to toggle source
# File lib/bitgirder/core.rb, line 740
def self.get_validation_listener

    if res = @@validation_listener
        @@validation_listener = nil
        res
    else
        lambda { |attr, e| } # no-op is default
    end
end
init_instance( inst, argv ) click to toggle source
# File lib/bitgirder/core.rb, line 801
def self.init_instance( inst, argv )
    self.for_class( inst.class ).init_instance( inst, argv )
end
new( opts ) click to toggle source
# File lib/bitgirder/core.rb, line 568
def initialize( opts )
    
    REQUIRED_ATTRS.each do |attr|

        val = BitGirderMethods.has_key( opts, attr )
        instance_variable_set( :"@#{attr}", val )
    end
end
validation_listener=( l ) click to toggle source
# File lib/bitgirder/core.rb, line 750
def self.validation_listener=( l )
    
    BitGirderMethods.not_nil( l, :l )
    raise "A validation listener is already set" if @@validation_listener
   
    @@validation_listener = l
end

Public Instance Methods

add_attr( arg ) click to toggle source
# File lib/bitgirder/core.rb, line 592
def add_attr( arg )

    attr = read_add_attr_arg( arg )
 
    if @attrs.key?( attr.identifier )
        msg = "Attribute #{attr.identifier.inspect} already defined"
        raise BitGirderAttribute::RedefinitionError, msg
    else
        ident = attr.identifier
        @attrs[ ident ] = attr
        @attr_syms << "@#{ident}".to_sym
        @decl_order << ident
        @cls.send( attr.mutable ? :attr_accessor : :attr_reader, ident )
    end
end
hash_instance( inst ) click to toggle source
# File lib/bitgirder/core.rb, line 729
def hash_instance( inst )
    @decl_order.map { |id| @attrs[ id ].get_instance_value( inst ) }.hash
end
init_instance( inst, argv ) click to toggle source
# File lib/bitgirder/core.rb, line 705
def init_instance( inst, argv )

    argh =
        if argv.size == 0
            {}
        else
            if argv.size == 1 and ( arg = argv[ 0 ] ).is_a?( Hash )
                arg
            else
                argv_to_argh( argv, @decl_order )
            end
        end

    trace = caller
    listener = BitGirderClassDefinition.get_validation_listener

    @attrs.each_pair { |ident, attr| 
        set_attr_value( inst, argh, ident, attr, trace, listener ) 
    }

    impl_initialize( inst )
end

Private Instance Methods

apply_processor( attr, val ) click to toggle source
# File lib/bitgirder/core.rb, line 614
def apply_processor( attr, val )

    if p = attr.processor
        if attr.is_list
            val = val.map { |elt| p.call( elt ) }
        else
            val = p.call( val )
        end
    else
        val
    end
end
get_initial_value( hash, ident, attr ) click to toggle source
# File lib/bitgirder/core.rb, line 628
def get_initial_value( hash, ident, attr )
    
    # Get the val as the caller-supplied one, which we allow to be either
    # the symbol or string form, supplying the default as needed; note that
    # we use key membership and explicit tests for nil instead of boolean
    # operators since we want to allow the value 'false' from the caller or
    # as a default
    val = hash.key?( ident ) ? hash[ ident ] : hash[ ident.to_s ]

    if val == nil 
        val = attr.get_default_value # could still end up being nil
    else 
        val = apply_processor( attr, val )
    end

    val
end
get_supplied_attr_value( hash, ident ) click to toggle source
# File lib/bitgirder/core.rb, line 609
def get_supplied_attr_value( hash, ident )
    hash[ ident ] || hash[ ident.to_s ]
end
impl_initialize( inst ) click to toggle source
# File lib/bitgirder/core.rb, line 697
def impl_initialize( inst )
    
    if inst.respond_to?( meth = :impl_initialize, true ) 
        inst.send( meth )
    end
end
read_add_attr_arg( arg ) click to toggle source
# File lib/bitgirder/core.rb, line 578
def read_add_attr_arg( arg )

    case arg
    when BitGirderAttribute then arg
    when Hash
        unless arg.key?( :required ) || arg.key?( :default )
            arg[ :required ] = true
        end
        BitGirderAttribute.new( arg )
    else raise "Don't know how to add as attr: #{arg}"
    end
end
set_attr_value( inst, hash, ident, attr, trace, listener ) click to toggle source
# File lib/bitgirder/core.rb, line 687
def set_attr_value( inst, hash, ident, attr, trace, listener )
 
    val = get_initial_value( hash, ident, attr )

    validate_attr_val( attr, val, trace, listener )

    inst.instance_variable_set( :"@#{attr.identifier}", val )
end
validate_attr_val( attr, val, trace, listener ) click to toggle source
# File lib/bitgirder/core.rb, line 667
def validate_attr_val( attr, val, trace, listener )
    
    begin

        if attr.is_list || attr.list_validation
            validate_list_attr_val( attr, val )
        else
            validate_scalar_attr_val( attr, val )
        end

        val

    rescue Exception => e

        listener.call( attr, e )
        raise e, "#{attr.identifier}: #{e.message}", trace
    end
end
validate_list_attr_val( attr, val ) click to toggle source
# File lib/bitgirder/core.rb, line 647
def validate_list_attr_val( attr, val )
    
    if list_func = attr.list_validation
        list_func.call( val )
    end

    if func = attr.validation
        val.each { |v| func.call( v ) }
    end
end
validate_scalar_attr_val( attr, val ) click to toggle source
# File lib/bitgirder/core.rb, line 659
def validate_scalar_attr_val( attr, val )
 
    if ( func = attr.validation ) && ( attr.required || ( ! val.nil? ) )
        func.call( val )
    end
end