# $Id: extent.rb 152 2003-06-04 15:02:50Z bolzer $
# Author:: Oliver M. Bolzer (mailto:oliver@fakeroot.net)
# Copyright:: (c) Oliver M. Bolzer, 2003
# Licence:: Ruby licence.
#
#:nodoc:

module Vapor

  # Container class for Persistable objects.
  # Retrieval of a Persistable is deferred until it is actually requested. 
  class Extent
    include Enumerable

    # Create a new Extent associated with the given PersistenceManager and 
    # containing persistent instances of the given class 
    def initialize( pmgr, klass, has_subclasses  = true ) #:nodoc:
    
      # check if first argument looks like a PersistenceManager
      raise ArgumentError.new( "first argument must respond to get_object")  unless pmgr.respond_to?( :get_object )
      raise ArgumentError.new( "second argument must by a Class" ) unless klass.is_a?( Class )

      # save class of objects to be contained
      @candidate_class = klass
      @subclasses = has_subclasses

      # save associated PersistenceManager
      @persistence_manager = pmgr

      @persistables = Array.new
    end # initialize()
    
    # class of Persistable instances contained
    attr_reader :candidate_class

    # associated PersistenceManager
    attr_reader :persistence_manager

    # Returns <tt>true</tt> if the extent includes instances of subclasses
    # of the candidate class.
    def has_subclasses?
      @subclasses
    end # has_subclasses?()

    # Add Persistable with specified OID. 
    def add( oid ) #:nodoc:
      raise ArgumentError.new( "OID must be Integer" ) unless oid.is_a?( Integer )

      if !@persistables.include?( oid ) then
        @persistables.push( oid )
      end

      return self
    end # add()
    alias :<< :add  #:nodoc:


    # Iterator over all Persistable instances contained.
    def each( &block )
      @persistables.each{|oid|
        persistable = @persistence_manager.get_object( oid )
        yield persistable 
      }
    end # each

    # Returns number of Persistable objects contained. Maybe zero.
    def size
      @persistables.size
    end # size()

    # Returns <tt>true</tt> if no Persistable objects are contained. 
    def empty?
     @persistables.empty?
    end # empty?

    # Returns <tt>Array</tt> of OIDs of the Persistable objects contained.
    def oid_array
      @persistables.clone
    end

    # Rturns n-th contained Persistable.
    def [](key)
      oid = @persistables[ key ]
      if oid then
        @persistence_manager.get_object( oid )
      else
        nil
      end
    end # []

  end # class Extent

end # module Vapor
  
