#!/usr/bin/env python
#############################################################################
# Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999
# All Rights Reserved.
#
# The software contained on this media is the property of the DSTC Pty
# Ltd.  Use of this software is strictly in accordance with the
# license agreement in the accompanying LICENSE.HTML file.  If your
# distribution of this software does not contain a LICENSE.HTML file
# then you have no rights to use this software in any manner and
# should contact DSTC at the address below to determine an appropriate
# licensing arrangement.
# 
#      DSTC Pty Ltd
#      Level 7, GP South
#      Staff House Road
#      University of Queensland
#      St Lucia, 4072
#      Australia
#      Tel: +61 7 3365 4310
#      Fax: +61 7 3365 4311
#      Email: enquiries@dstc.edu.au
# 
# This software is being provided "AS IS" without warranty of any
# kind.  In no event shall DSTC Pty Ltd be liable for damage of any
# kind arising out of or in connection with the use or performance of
# this software.
#
# Project:      Fnorb
# File:         $Source: /projects/fnorb/Fnorb-1.1/orb/RCS/TypeManager.py,v $
# Version:      @(#)$RCSfile: TypeManager.py,v $ $Revision: 1.6 $
#
#############################################################################
""" Type Manager. """


# Fnorb modules.
import fnorb_thread


# fixme: Is this too slow?  Should we just create an instance when the module
# is loaded and reference it as a module scope variable?
def TypeManager_init():
    """ Return the Type Manager. 

    This is a factory function for the TypeManager class (the Type Manager
    is a singleton (ie. there can only be one instance per process)).

    """
    try:
	tm = TypeManager()

    except TypeManager, tm:
	pass

    return tm


class TypeManager:
    """ The Type Manager.

    The Type Manager is a singleton (ie. there can only be one instance per
    process).

    """
    __instance = None


    def __init__(self):
	""" Constructor. """

 	# The Type Manager is a singleton (ie. there can only be one instance
	# per process).
	if TypeManager.__instance is not None:
 	    raise TypeManager.__instance

	TypeManager.__instance = self

	# Type dictionary.
	self.__types = {} # {RepositoryId : (TypeCodeConstant, PythonObject)}

	# Interface repository id dictionary.
	self.__ifr_ids = {} # {id(PythonObject) : RepositoryId}

	# Mutex to make access to the dictionaries thread-safe.
	self.__lk = fnorb_thread.allocate_lock()

	return

    def add_type(self, ifr_id, typecode_constant, py_object):
	""" Add a typecode constant to the typecode dictionary! """

	self.__lk.acquire()
	self.__types[ifr_id] = (typecode_constant, py_object)
	self.__ifr_ids[id(py_object)] = ifr_id
	self.__lk.release()
	
	return

    def get_typecode_constant(self, ifr_id):
	""" Get the typecode for the specified interface repository ID.

	Returns 'None' if the ID is not found.

	"""
	self.__lk.acquire()
	try:
	    (typecode_constant, py_object) = self.__types[ifr_id]

	except KeyError:
	    raise 'No constant for this typecode!'
	    typecode_constant = None

	self.__lk.release()
	return typecode_constant

    def get_python_object(self, ifr_id):
	""" Get the Python object for the specified interface repository ID.

	Returns 'None' if the ID is not found.

	"""
	self.__lk.acquire()
	try:
	    (typecode_constant, py_object) = self.__types[ifr_id]

	except KeyError:
	    py_object = None
	self.__lk.release()

	return py_object

    def get_ifr_id(self, py_object):
	""" Get the interface repository ID for the specified Python object.

	Returns 'None' if the object is not found.

	"""
	self.__lk.acquire()
	ifr_id = self.__ifr_ids.get(id(py_object))
	self.__lk.release()

	return ifr_id

#############################################################################
