generic
type Object_Class (<>) is abstract tagged limited private;
type Object_Access is access Object_Class'Class;
with procedure Delete( e : in out Object_Access );
-- This generic package is used to register an association of object class
-- names and allocators. This allows us to instantiate an object simply by class
-- name, without ever referencing its implementation in the code.
package Object_Factory is
type Allocator is access function return Object_Access;
-- Initializes the factory by name. The name should be the root type of
-- objects that it manufactures. (ex: "entity", "actor", etc). Classes
-- should be registered before the factory is initialized, preferably at
-- elaboration time. Template instances of each registered class are created
-- at initialization. An exception will be raised on error, from the first
-- failure to instantiate a template instance.
procedure Initialize( factoryName : String );
pragma Precondition( factoryName'Length > 0 );
-- Finalizes the factory, deleting template instances.
procedure Finalize;
-- Returns null if no allocator is registered for the given class id. If
-- the allocator registered for 'id' raises an exception, it will be passed
-- on to the caller.
function Allocate( id : String ) return Object_Access;
pragma Precondition( id'Length > 0 );
-- Iterate over the registered class id strings.
procedure Iterate_Classes( examine : access procedure( id : String ) );
-- Registers a class allocation function with a class id.
procedure Register_Class( id : String; allocate : not null Allocator );
pragma Precondition( id'Length > 0 );
-- Returns a reference to a template instantiation of the class registered
-- with 'id'. Template entities are instantiated when the factory package is
-- initialized. If no class is registered for the id, null will be returned.
-- Do not modify the object that is returned!
function Template( id : String ) return Object_Access;
pragma Precondition( id'Length > 0 );
end Object_Factory;