########################################################################
#
# File Name: 	       Union.py
#
# Documentation:	http://docs.ftsuite.com/4ODS/Collection.py.html
#
"""
Implements the Union interface.
WWW: http://4suite.org/4ODS         e-mail: support@4suite.org

Copyright (c) 2001 Fourthought Inc, USA.   All Rights Reserved.
See  http://4suite.org/COPYRIGHT  for license and copyright information
"""

import string
from Ft.Ods import Constants
from Ft.Ods.Exception import FtodsUnsupportedError

class Union:

    _switchType = None
    _cases = {}
    _defaultCase = None
    def __init__(self,db,data):
        #NOTE: db could be None which is alright for a new Union instance
        self.__dict__['_db'] = db
        self.__dict__['_savedData'] = None

        if data is None:
            #Setup the default case
            d = self._defaultCase
            if not self._cases.has_key(self._defaultCase):
                return 
            name, typ, default = self._cases[d]

            if Constants.g_primitiveTypes[typ]:
                v = default
                Constants.g_typeCheck[typ](v,-1)
            elif typ in [Constants.Types.POBJECT,
                         Constants.Types.ROBJECT]:
                v = None
            elif Constants.g_literalTypes[typ]:
                v = self._db._4ods_createLiteralInstance(typ,default)
            elif Constants.g_listTypes[typ]:
                v = None
            else:
                raise FtodsUnsupportedError(feature="Union Cases of type %s" % typ)

            self.__dict__['_d'] = d
            self.__dict__['_v'] = v
            self.__dict__[name] = v
            self.__dict__['_type'] = typ
        else:


            if data[0] is not None:
                #From the user
                d,v = data
                if self._switchType == Constants.Types.ENUMERATION:
                    useD = d._v
                else:
                    useD = d

            else:
                #From the DB
                data = data[1]
                useD = data[0][0]
                if self._switchType == Constants.Types.ENUMERATION:
                    d = self._db.current()._4ods_createLiteralInstance(Constants.Types.ENUMERATION,self._switchRepoId,(useD,))
                else:
                    d = useD

                curName = self._cases[useD][0]
                index = list(self._tupleNames).index(curName)
                v = data[index+1]

            name, typ, default = self._cases[useD]

            if Constants.g_primitiveTypes[typ]:
                if type(v) == type(()):
                    v = v[0]
                Constants.g_typeCheck[typ](v,-1)
            elif typ in [Constants.Types.POBJECT,
                         Constants.Types.ROBJECT]:
                if type(v) == type(()):
                    v = v[0]
                if type(v) == type(1):
                    v = self._db._4ods_getPersistentObjectById(typ,v)
                else:
                    Constants.g_typeCheck[typ](v,default)
            elif Constants.g_literalTypes[typ]:
                if type(v) in [type(()),type(1)]:
                    v = self._db.current()._4ods_createLiteralInstance(typ,default,v)
                else:
                    Constants.g_typeCheck[typ](v,default)
            elif Constants.g_listTypes[typ]:
                if type(v) == type(()):
                    v = v[0]
                if type(v) == type(1):
                    v = self._db._4ods_getPersistentObjectById(typ,v)
                else:
                    Constants.g_typeCheck[typ](v,default)
            else:
                raise FtodsUnsupportedError(feature="Union Cases of type %s" % typ)

            self.__dict__['_d'] = d
            self.__dict__['_v'] = v
            self.__dict__[name] = v
            self.__dict__['_type'] = typ


    def _4ods_getData(self):

        if self._switchType == Constants.Types.ENUMERATION:
            useD = self._d._v
        else:
            useD = self._d

        data = [(useD,)]
            
        for name in self._tupleNames:

            for case,(n,typ,default) in self._cases.items():
                if name == n:
                    break


            if case == useD:
                if Constants.g_primitiveTypes[typ]:            
                    value = (self._v,)
                elif typ in [Constants.Types.POBJECT,
                             Constants.Types.ROBJECT]:
                    value = self._v
                    if value is not None:
                        value = (value._4ods_getId(),)
                elif Constants.g_literalTypes[typ]:
                    value = self._v._4ods_getData()
                elif Constants.g_listTypes[typ]:
                    value = self._v
                    if value is not None:
                        value = (value._4ods_getId(),)
                else:
                    raise FtodsUnsupportedError(feature="Union Members of type %s" % typ)
            else:
                value = None

            data.append(value)

        
        return (None,tuple(data))

        
    def __cmp__(self,other):
        if isinstance(other,Union):
            if self._v == other._v and self._d == other._d: return 0
        return 1

    def __str__(self):
        return "<Union _d=%s, _v = %s at %x>" % (self._d, self._v, id(self))

    def _4ods_isModified(self):
        return 1
