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

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

from Ft.Ods.StorageManager.Adapters import Constants

from Ft.Ods import Database
from Ft.Ods import PersistentObject

from Ft.Ods.Exception import IntegrityError, FtodsUnknownError

from Ft.Ods.PersistentObject import TupleDefinitions

from Ft.Ods.StorageManager.Adapters import Constants

from Ft.Ods.MetaData import MetaKind
import Ft.Ods.MetaData

class RepositoryObject(PersistentObject.PersistentObject):

    def __init__(self, db,data,meta_kind):

        #Initilize maybe
        if data is None:
            if not MetaKind.MetaKind.isMember(meta_kind):
                raise FtodsUnknownError(msg="What are you doing?  You need to specify a meta kind")
            self.__dict__['meta_kind'] = meta_kind

        PersistentObject.PersistentObject.__init__(self, db, data)



    def parent(self):
        return None

    def absolute_name(self):
        return self.__dict__.get('name', '')

    def _4ods_setRepositoryId(self, rid):
        self.__dict__['_repoId'] = rid

    def _4ods_getId(self):
        return self.__dict__['_repoId']


    def _4ods_formRelationship(self,name,targetType,inverseName,inverseType,val,inverse):
        if not isinstance(val,targetType):
            raise IntegrityError(relName=name)
        #Only allowed to be in a relationship with one person
        if getattr(self,name):
            raise IntegrityError(relName=name)
            
        self.__dict__[name] = val
        if inverse:
            if inverseType == 'add':
                val._4ods_addRelationship(inverseName,self.__class__,name,'form',self,0)
            elif inverseType == 'form':
                val._4ods_formRelationship(inverseName,self.__class__,name,'form',self,0)
            else:
                raise FtodsUnknownError(msg="Invalid Relationship inverse function %s" % inverseType)
        self.__dict__['_modifiedAttrs'][name] = 1

    def _4ods_dropRelationship(self,name,inverseName,inverseType,val,inverse):
        if self.__dict__.has_key(name):
            if self.__dict__[name] != val:
                raise IntegrityError(relName=name)
        elif not self.__dict__['_objectIds'].has_key(name) and self.__dict__['_objectIds'][name] != val._4ods_getId():
                raise IntegrityError(relName=name)

        if self.__dict__.has_key(name):
            del self.__dict__[name]
        if self.__dict__['_objectIds'].has_key(name):
            del self.__dict__['_objectIds'][name]
            
        if inverse:
            if inverseType == 'remove':
                val._4ods_removeRelationship(inverseName,name,'drop',self,0)
            elif inverseType == 'drop':
                val._4ods_dropRelationship(inverseName,name,'drop',self,0)
            else:
                raise FtodsUnknownError(msg="Invalid Relationship inverse function %s" % inverseType)

        self.__dict__['_modifiedAttrs'][name] = 1

    def _4ods_addRelationship(self,name,targetType,inverseName,inverseType,val,inverse):
        if not isinstance(val,targetType):
            raise IntegrityError(relName=name)
        ourColl = getattr(self,name)
        if not ourColl.allows_duplicates() and ourColl.contains_element(val):
            raise IntegrityError(relName=name)
        ourColl.insert_element(val)
        if inverse:
            if inverseType == 'add':
                val._4ods_addRelationship(inverseName,self.__class__,name,'add',self,0)
            elif inverseType == 'form':
                val._4ods_formRelationship(inverseName,self.__class__,name,'add',self,0)
            else:
                raise FtodsUnknownError(msg="Invalid Relationship inverse function %s" % inverseType)

    def _4ods_removeRelationship(self,name,inverseName,inverseType,val,inverse):
        ourColl = getattr(self,name)
        if not ourColl.contains_element(val):
            raise IntegrityError(relName=name)
        ourColl.remove_element(val)
        if inverse:
            if inverseType == 'remove':
                val._4ods_removeRelationship(inverseName,name,'remove',self,0)
            elif inverseType == 'drop':
                val._4ods_dropRelationship(inverseName,name,'remove',self,0)
            else:
                raise FtodsUnknownError(msg="Invalid Relationship inverse function %s" % inverseType)



    def _4ods_getOdsType(self):
        return Constants.Types.ROBJECT


    def __repr__(self):
        return "<%s at %s rid=%d>" % (self.__class__.__name__,hex(id(self)),self.__dict__.get('_repoId',0))

    _tupleNames =  (('_repoId',),('meta_kind',))


    _tupleDefinitions = {'_repoId': {TupleDefinitions.TYPE:Constants.Types.UNSIGNED_SHORT,
                                     TupleDefinitions.READONLY:1,
                                     },
                         'meta_kind':{TupleDefinitions.TYPE:Constants.Types.ENUMERATION,
                                      TupleDefinitions.READONLY:1,
                                      TupleDefinitions.LITERAL_REPO_ID:MetaKind.MetaKind._typeId,
                                      },
                         }
                                      

    _localExtents = ()
                         
