#!/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/IOP.py,v $
# Version:      @(#)$RCSfile: IOP.py,v $ $Revision: 1.18 $
#
#############################################################################
""" CORBA Interoperability (IOP) module. """


_FNORB_ID = "IDL:omg.org/IOP:1.0"


# Standard/built-in modules.
import new, string

# Fnorb modules.
import CORBA, IIOP, OctetStream, TypeManager

# Fnorb extension modules.
import cdr


# Alias: IDL:omg.org/IOP/ProfileId:1.0
TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/ProfileId:1.0", "0000000000000005", None)

# Constant: IDL:omg.org/IOP/TAG_INTERNET_IOP:1.0
TAG_INTERNET_IOP = 0L

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/TAG_INTERNET_IOP:1.0", "0000000000000005", TAG_INTERNET_IOP)

# Constant: IDL:omg.org/IOP/TAG_MULTIPLE_COMPONENTS:1.0
TAG_MULTIPLE_COMPONENTS = 1L

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/TAG_MULTIPLE_COMPONENTS:1.0", "0000000000000005", TAG_MULTIPLE_COMPONENTS)


class TaggedProfile:
    """ Struct: IDL:omg.org/IOP/TaggedProfile:1.0 """

    _FNORB_ID = "IDL:omg.org/IOP/TaggedProfile:1.0"

    def __init__(self, _tag, _profile_data):
        """ Constructor. """

        self.tag = _tag
        self.profile_data = _profile_data
        return

    def __getinitargs__(self):
        """ Return the constructor arguments for unpickling. """

        return (self.tag, self.profile_data)

    def _fnorb_marshal(self, cursor):
	""" Marshal the structure onto an octet stream. """

	cursor.marshal('L', self.tag)

	# The profile data is an encapsulation.
	encapsulation = OctetStream.Encapsulation()
	encapsulation_cursor = encapsulation.cursor()

	if self.tag == TAG_INTERNET_IOP:
	    tc = CORBA.typecode('IDL:omg.org/IIOP/ProfileBody:1.0')
	    tc._fnorb_marshal_value(encapsulation_cursor, self.profile_data)
	    
	elif self.tag == TAG_MULTIPLE_COMPONENTS:
 	    tc = CORBA.typecode('IDL:omg.org/IOP/TaggedComponent:1.0')
	    encapsulation_cursor.marshal('L', len(self.profile_data))
	    for component in self.profile_data:
		tc._fnorb_marshal_value(encapsulation_cursor, component)

	else:
	    # Unknown profile
	    encapsulation = self.profile_data

	cursor.marshal('O', encapsulation.data())
	return

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

	self.tag = cursor.unmarshal('L')

	# The profile data is an encapsulation.
	encapsulation = OctetStream.Encapsulation(cursor.unmarshal('O'))
	encapsulation_cursor = encapsulation.cursor()

	if self.tag == TAG_INTERNET_IOP:
	    tc = CORBA.typecode('IDL:omg.org/IIOP/ProfileBody:1.0')
	    self.profile_data = tc._fnorb_unmarshal_value(encapsulation_cursor)
	    
	elif self.tag == TAG_MULTIPLE_COMPONENTS:
	    tc = CORBA.typecode('IDL:omg.org/IOP/TaggedComponent:1.0')
	    self.profile_data = [] # [TaggedComponent]
	    for i in range(encapsulation_cursor.unmarshal('L')):
		component = tc._fnorb_unmarshal_value(encapsulation_cursor)
		self.profile_data.append(component)

	else:
	    # Unknown profile, simply store it
	    self.profile_data = encapsulation

	return

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/TaggedProfile:1.0", "000000000000000F000000B8000000000000002249444C3A6F6D672E6F72672F494F502F54616767656450726F66696C653A312E300000000000000E54616767656450726F66696C65000000000000020000000474616700000000150000003C000000000000001E49444C3A6F6D672E6F72672F494F502F50726F66696C6549643A312E300000000000000A50726F66696C654964000000000000050000000D70726F66696C655F6461746100000000000000130000000C000000000000000A00000000", TaggedProfile)

class IOR:
    """ Struct: IDL:omg.org/IOP/IOR:1.0 """

    _FNORB_ID = "IDL:omg.org/IOP/IOR:1.0"

    # Custom default parameters used to create a 'nil' object reference.
    def __init__(self, _type_id='', _profiles=[]):
        """ Constructor. """

        self.type_id = _type_id
        self.profiles = _profiles

        return

    def __getinitargs__(self):
        """ Return the constructor arguments for unpickling. """

        return (self.type_id, self.profiles)

    def _fnorb_from_string(self, stringified_ior):
	""" Initialise the IOR instance from the stringified IOR. """

	# Get rid of any dubious (and technically illegal) characters at the
	# start of the IOR (apparently some Java ORBs do this 8^()
	stringified_ior = stringified_ior[string.find(stringified_ior,"IOR:"):]

	# Get rid of any whitespace around the IOR (we're a pretty tolerant
	# bunch round here ;^).
	stringified_ior = string.strip(stringified_ior)

	# The first four characters MUST be 'IOR:'!
	if stringified_ior[:4] != 'IOR:':
	    raise CORBA.INV_OBJREF() # System exception.

	# Convert the rest of the stringified IOR from ASCII into an octet
	# stream (ie. a sequence of octets). Each pair of ASCII characters
	# makes a single octet.
	octets = cdr.ASCII_to_octet(stringified_ior[4:])

	# The IOR is contained in a CORBA 'encapsulation'.
	octet_stream = OctetStream.Encapsulation(octets)
	cursor = octet_stream.cursor()

	# Unmarshal the IOR from the encapsulation.
	self._fnorb_unmarshal(cursor)
	
	return

    def _fnorb_to_string(self):
	""" Convert the IOR instance into a stringified object reference. """

	# The IOR is marshalled into a CORBA 'encapsulation'.
	encapsulation = OctetStream.Encapsulation()
	cursor = encapsulation.cursor()

	# Marshal the IOR into the encapsulation.
	self._fnorb_marshal(cursor)

	# Convert the octet stream into an ASCII string.  Each octet is
	# represented by a pair of ASCII characters.
	stringified_ior = cdr.octet_to_ASCII(encapsulation.data())

	return 'IOR:' + stringified_ior

    def _fnorb_iiop_profile(self):
	""" Return the IOR's IIOP profile. """

	# Fnorb can only deal with IOR's that come from ORB's that support
	# IIOP!  If the IOR does NOT contain an IIOP profile, then raise an
	# appropriate system exception.
	for p in self.profiles:
	    if p.tag == TAG_INTERNET_IOP:
		break
	else:
	    raise CORBA.INV_OBJREF() # System exception.

	return p.profile_data

    def _fnorb_marshal(self, cursor):
        """ Marshal the structure onto an octet stream. """

        cursor.marshal('s', self.type_id)
        cursor.marshal('L', len(self.profiles))
        for i0 in range(len(self.profiles)):
            self.profiles[i0]._fnorb_marshal(cursor)

        return

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

        self.type_id = cursor.unmarshal('s')
        self.profiles = []
        for i0 in range(cursor.unmarshal('L')):
            self.profiles_i0 = new.instance(TaggedProfile, {})
	    self.profiles_i0._fnorb_unmarshal(cursor)
	    self.profiles.append(self.profiles_i0)
 
	return

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/IOR:1.0", "000000000000000F00000120000000000000001849444C3A6F6D672E6F72672F494F502F494F523A312E300000000004494F52000000000200000008747970655F69640000000012000000000000000970726F66696C65730000000000000013000000C8000000000000000F000000B8000000000000002249444C3A6F6D672E6F72672F494F502F54616767656450726F66696C653A312E300000000000000E54616767656450726F66696C65000000000000020000000474616700000000150000003C000000000000001E49444C3A6F6D672E6F72672F494F502F50726F66696C6549643A312E300000000000000A50726F66696C654964000000000000050000000D70726F66696C655F6461746100000000000000130000000C000000000000000A0000000000000000", IOR)

# Alias: IDL:omg.org/IOP/ComponentId:1.0
TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/ComponentId:1.0", "0000000000000005", None)


class TaggedComponent:
    """ Struct: IDL:omg.org/IOP/TaggedComponent:1.0 """

    _FNORB_ID = "IDL:omg.org/IOP/TaggedComponent:1.0"

    def __init__(self, _tag, _component_data):
        """ Constructor. """

        self.tag = _tag
        self.component_data = _component_data
        return

    def __getinitargs__(self):
        """ Return the constructor arguments for unpickling. """

        return (self.tag, self.component_data)


TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/TaggedComponent:1.0", "000000000000000F000000B8000000000000002449444C3A6F6D672E6F72672F494F502F546167676564436F6D706F6E656E743A312E300000000010546167676564436F6D706F6E656E7400000000020000000474616700000000150000003C000000000000002049444C3A6F6D672E6F72672F494F502F436F6D706F6E656E7449643A312E30000000000C436F6D706F6E656E74496400000000050000000F636F6D706F6E656E745F646174610000000000130000000C000000000000000A00000000", TaggedComponent)

# Alias: IDL:omg.org/IOP/MultipleComponentProfile:1.0
TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/MultipleComponentProfile:1.0", "0000000000000013000000C8000000000000000F000000B8000000000000002449444C3A6F6D672E6F72672F494F502F546167676564436F6D706F6E656E743A312E300000000010546167676564436F6D706F6E656E7400000000020000000474616700000000150000003C000000000000002049444C3A6F6D672E6F72672F494F502F436F6D706F6E656E7449643A312E30000000000C436F6D706F6E656E74496400000000050000000F636F6D706F6E656E745F646174610000000000130000000C000000000000000A0000000000000000", None)

# Alias: IDL:omg.org/IOP/ServiceId:1.0
TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/ServiceId:1.0", "0000000000000005", None)


class ServiceContext:
    """ Struct: IDL:omg.org/IOP/ServiceContext:1.0 """

    _FNORB_ID = "IDL:omg.org/IOP/ServiceContext:1.0"

    def __init__(self, _context_id, _context_data):
        """ Constructor. """

        self.context_id = _context_id
        self.context_data = _context_data
        return

    def __getinitargs__(self):
        """ Return the constructor arguments for unpickling. """

        return (self.context_id, self.context_data)

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/ServiceContext:1.0", "000000000000000F000000C0000000000000002349444C3A6F6D672E6F72672F494F502F53657276696365436F6E746578743A312E3000000000000F53657276696365436F6E746578740000000000020000000B636F6E746578745F69640000000000150000003C000000000000001E49444C3A6F6D672E6F72672F494F502F5365727669636549643A312E300000000000000A536572766963654964000000000000050000000D636F6E746578745F6461746100000000000000130000000C000000000000000A00000000", ServiceContext)

# Alias: IDL:omg.org/IOP/ServiceContextList:1.0
TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/ServiceContextList:1.0", "0000000000000013000000D0000000000000000F000000C0000000000000002349444C3A6F6D672E6F72672F494F502F53657276696365436F6E746578743A312E3000000000000F53657276696365436F6E746578740000000000020000000B636F6E746578745F69640000000000150000003C000000000000001E49444C3A6F6D672E6F72672F494F502F5365727669636549643A312E300000000000000A536572766963654964000000000000050000000D636F6E746578745F6461746100000000000000130000000C000000000000000A0000000000000000", None)

# Constant: IDL:omg.org/IOP/TransactionService:1.0
TransactionService = 0L

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/TransactionService:1.0", "0000000000000005", TransactionService)

# Constant: IDL:omg.org/IOP/CodeSets:1.0
CodeSets = 1L

TypeManager.TypeManager_init().add_type("IDL:omg.org/IOP/CodeSets:1.0", "0000000000000005", CodeSets)

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