#!/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/Any.py,v $
# Version:      @(#)$RCSfile: Any.py,v $ $Revision: 1.12 $
#
#############################################################################
""" Implementation of CORBA Any type. """


# Fnorb modules.
import CORBA


class Any:
    """ Implementation of CORBA Any type. """

    def __init__(self, typecode, value):
	""" Constructor.
	
	typecode -> TypeCode
	value -> A value of the appropriate type

	"""
	self.__typecode = typecode
	self.__value = value

	return

    #########################################################################
    # CORBA interface.
    #########################################################################

    def typecode(self):
	""" Return the TypeCode of the Any. """

	return self.__typecode

    def value(self):
	""" Return the value of the Any. """

	return self.__value

    #########################################################################
    # Fnorb-specific interface.
    #########################################################################
	
    def _fnorb_marshal(self, cursor):
	""" Marshal myself onto an octet stream. """

	self.__typecode._fnorb_marshal(cursor)
	self.__typecode._fnorb_marshal_value(cursor, self.__value)

	return

    def _fnorb_unmarshal(self, cursor):
	""" Unmarshal myself from an octet stream. """

	self.__typecode = CORBA.TypeCodeFactory_init().unmarshal(cursor)
	self.__value = self.__typecode._fnorb_unmarshal_value(cursor)

	return

    #########################################################################
    # Methods for 'Any' arithmetic!
    # 
    # Arithmetic can only be performed on numeric (integer and floating point)
    # 'Any's.
    #
    # Mixed mode arithmetic is not allowed.
    #
    #########################################################################

    def __add__(self, other):
	""" Addition ;^) """

	# Type checking.
	result_type = self.__check_numeric_types(other)

	return Any(result_type, self.__value + other.__value)

    def __sub__(self, other):
	""" Subtraction ;^) """

	# Type checking.
	result_type = self.__check_numeric_types(other)

	return Any(result_type, self.__value - other.__value)

    def __mul__(self, other):
	""" Multiplication ;^) """

	# Type checking.
	result_type = self.__check_numeric_types(other)

	return Any(result_type, self.__value * other.__value)

    def __div__(self, other):
	""" Division ;^) """

	# Type checking.
	result_type = self.__check_numeric_types(other)

	return Any(result_type, self.__value / other.__value)

    def __lshift__(self, other):
	""" Left shift ;^) """

	# Type checking.
	result_type = self.__check_integer_types(other)

	return Any(result_type, self.__value << other.__value)

    def __rshift__(self, other):
	""" Right shift ;^) """

	# Type checking.
	result_type = self.__check_integer_types(other)

	return Any(result_type, self.__value >> other.__value)

    def __and__(self, other):
	""" And ;^) """

	# Type checking.
	result_type = self.__check_integer_types(other)

	return Any(result_type, self.__value & other.__value)

    def __xor__(self, other):
	""" Exclusive Or ;^) """

	# Type checking.
	result_type = self.__check_integer_types(other)

	return Any(result_type, self.__value ^ other.__value)

    def __or__(self, other):
	""" Or ;^) """

	# Type checking.
	result_type = self.__check_integer_types(other)

	return Any(result_type, self.__value | other.__value)

    def __neg__(self):
	""" Unary '-' """

	# Type checking.
	if self.__typecode.kind() not in Any.__TK_INT:
	    raise TypeError, "Operation not allowed on this type."

	return Any(self.__typecode, -self.__value)

    def __pos__(self):
	""" Unary '+' """

	# Type checking.
	if self.__typecode.kind() not in Any.__TK_INT:
	    raise TypeError, "Operation not allowed on this type."

	return Any(self.__typecode, +self.__value)

    def __invert__(self):
	""" Unary '~' """

	# Type checking.
	if self.__typecode.kind() not in Any.__TK_INT:
	    raise TypeError, "Operation not allowed on this type."

	return Any(self.__typecode, ~self.__value)

    #########################################################################
    # Private interface.
    #########################################################################

    # Integer typecode kinds.
    __TK_INT = [CORBA.tk_short,  CORBA.tk_long,  CORBA.tk_longlong,
		CORBA.tk_ushort, CORBA.tk_ulong, CORBA.tk_ulonglong]

    # Floating point typecode kinds.
    __TK_FP  = [CORBA.tk_float, CORBA.tk_double]
	
    def __check_numeric_types(self, other):
	""" Type checking for 'Any' arithmetic. """

	if self.__typecode.kind() in Any.__TK_FP:
	    if other.__typecode.kind() in Any.__TK_FP:
		result = CORBA.TC_double

	    else:
		raise TypeError, "Mixed mode arithmetic not allowed."

	elif self.__typecode.kind() in Any.__TK_INT:
	    if other.__typecode.kind() in Any.__TK_INT:
		result = CORBA.TC_longlong

	    else:
		raise TypeError, "Mixed mode arithmetic not allowed."

	elif self.__typecode.kind() == CORBA.tk_fixed:
	    if other.__typecode.kind() == CORBA.tk_fixed:
		result = CORBA.FixedTypeCode(0, 0)

	    else:
		raise TypeError, "Mixed mode arithmetic not allowed."
	
	else:
	    raise TypeError, "Operation not allowed on these types."

	return result

    def __check_integer_types(self, other):
	""" Type checking for 'Any' arithmetic. """

	if self.__typecode.kind() in Any.__TK_INT:
	    if other.__typecode.kind() in Any.__TK_INT:
		result = CORBA.TC_long

	    else:
		raise TypeError, "Mixed mode arithmetic not allowed."

	else:
	    raise TypeError, "Operation not allowed on these types."

	return result

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

