# $Id: oidgenerator.rb 137 2003-06-01 15:39:17Z bolzer $
# Author:: Oliver M. Bolzer (mailto:oliver@fakeroot.net)
# Copyright:: (c) Oliver M. Bolzer, 2002
# Licence:: Ruby licence.
#
##:nodoc:

require 'vapor/exceptions'

module Vapor
  include Exceptions

# generates Object-IDs (OIDs) that are uniqueue throughout a Repository's
# lifetime: past, present and future. All persistent objects in Vapor have
# such an unique OID.
#
# The OID is a compound of a HIGH and a LOW number. The HIGH number is 
# requested from a external source and cached. It then is combined with an
# OIDGenerator's own internally managed LOW number to form the OID.
class OIDGenerator #:nodoc:

  LOW_MAX = 65535 # 2^16 -1 (16-bit)

  # create a new OIDGenerator which does not (yet) know about it's 
  # source for HIGH numbers
  def initialize
    @high_value = nil
    @high_source = nil
    @low_value = -1
  end
 
  # assign a source for HIGH numbers.
  # 
  # Raises a HighSourceNotSetException if the source does not respond to
  # next_oid_high()
  def high_source=( source )

## inteferes with testing using Mock objects
## they don't respond to the method, though you can execute it
#    if !source.respond_to?( :next_oid_high ) then
#      raise HighSourceNotSetException, "high_source not responding to next_oid_high()"
#    end

    @high_source = source
  end

  # generate an unique OID
  #
  # Raises a HighSourceNotSetException if the source for HIGH numbers is not
  # set or the number gotten from it is invalid
  def next_oid
    if @high_value.nil? then      # no HIGH assigned
      if @high_source.nil? then
        raise HighSourceNotSetException
      else
        @high_value = @high_source.next_oid_high
	if @high_value > 281474976710655 or @high_value < -281474976710656 then # value not in boud of 48-bit signed integer
	  raise HighSourceNotSetException
	end

      end
    end

    ## increment LOW and wrap around if too big
    @low_value += 1
    
    if @low_value > LOW_MAX then
      @low_value = 0
    end
   
    ## compute OID
    oid = (@high_value << 16) + @low_value

    return oid
  end

end # class OIDGenerator

end # module Vapor
