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

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

import string
from Ft.Ods import Constants, Collections

from Ft.Ods.Exception import FtodsUnsupportedError

class Structure:
    _definition = {}
    
    def __init__(self,db,data=None):

        self.__dict__['_db'] = db
        self.__dict__['_savedData'] = {}
        if data:
            data = data[1]
            for name,d in map(None,self._tupleNames,data):
                typ,default = self._definition[name]
                if Constants.g_primitiveTypes[typ]:
                    value = d[0]
                elif typ in [Constants.Types.POBJECT,
                             Constants.Types.ROBJECT]:
                    self.__dict__['_savedData'][name] = d[0]
                    continue
                elif Constants.g_literalTypes[typ]:
                    self.__dict__['_savedData'][name] = d
                    continue
                elif Constants.g_listTypes[typ]:
                    value = self._db._4ods_getPersistentObjectById(typ,d[0])
                else:
                    raise FtodsUnsupportedError(feature="Structure Members of type %s" % typ)

                self.__dict__[name] = value
            self.__dict__['_modified'] = 0
        else:
            #Set the default values
            for name,(typ,default) in self._definition.items():
                if Constants.g_primitiveTypes[typ]:
                    value = default
                elif typ in [Constants.Types.POBJECT, Constants.Types.ROBJECT]:
                    self.__dict__['_savedData'][name] = None
                    continue
                elif Constants.g_literalTypes[typ]:
                    self.__dict__['_savedData'][name] = None
                    continue
                elif Constants.g_listTypes[typ]:
                    (ct,st,strid,kt,ktrid) = default
                    value = Collections.CollectionFromTypes(db,
                                                            ct,
                                                            st,
                                                            keyType=kt,
                                                            subTypeRepositoryId = strid,
                                                            keyTypeRepositoryId = ktrid)
                else:
                    raise FtodsUnsupportedError(feature="Structure Members of type %s" % typ)


                self.__dict__[name] = value
            self.__dict__['_modified'] = 1
                

    def __getattr__(self,name):
        defs = self._definition
        if name in defs.keys():
            typ,default = defs[name]
            d = self.__dict__['_savedData'][name]
            if typ in [Constants.Types.POBJECT,
                       Constants.Types.ROBJECT]:
                if d:
                    value = self._db._4ods_getPersistentObjectById(typ,d)
                else:
                    value = None
            elif Constants.g_literalTypes[typ]:
                value = self._db.current()._4ods_createLiteralInstance(typ,default,d)
            self.__dict__[name] = value
            return value
        else:
            raise AttributeError(name)
        
    def __setattr__(self,name,value):
        defs = self._definition
        if name in defs.keys():
            typ,default = defs[name]
            if Constants.g_primitiveTypes[typ]:
                Constants.g_typeCheck[typ](value,-1)
            elif typ in [Constants.Types.POBJECT,
                         Constants.Types.ROBJECT]:
                Constants.g_typeCheck[typ](value,default)
            elif typ == Constants.Types.STRUCTURE:
                raise AttributeError("You cannot set a structure attribute")
            elif Constants.g_literalTypes[typ]:
                Constants.g_typeCheck[typ](value,default)
            elif Constants.g_listTypes[typ]:
                raise AttributeError("You cannot set a structure attribute")
            else:
                raise FtodsUnsupportedError(feature="Structure Members of type %s" % typ)

            self.__dict__['_modified'] = 1
        self.__dict__[name] = value
        
    def _4ods_isModified(self):
        return self.__dict__['_modified']

    def _4ods_getData(self):

        data = []
        for name in self._tupleNames:
            (typ,default) = self._definition[name]
            if Constants.g_primitiveTypes[typ]:            
                value = (self.__dict__[name],)
            elif typ in [Constants.Types.POBJECT,
                         Constants.Types.ROBJECT]:
                value = self.__dict__.get(name)
                if value is not None:
                    value = (value._4ods_getId(),)
            elif Constants.g_literalTypes[typ]:
                value = self.__dict__[name]._4ods_getData()
            elif Constants.g_listTypes[typ]:
                value = self.__dict__.get(name)
                if value is not None:
                    value = (value._4ods_getId(),)
            else:
                raise FtodsUnsupportedError(feature="Structure Members of type %s" % typ)
            data.append(value)

        return (None,tuple(data))

    def __cmp__(self,other):
        if isinstance(other,Structure):
            #Structures don't have IDS so we must compare the data
            if self._typeId != other._typeId: return 1
            for name,(typ,default) in self._definition.items():
                d = self.__dict__[name]
                if not other.__dict__.has_key(name): return 1
                if other.__dict__[name] != d: return 1
            return 0
        return 1

