########################################################################
#
# File Name: 	        Interface.py
#
# Documentation:	http://docs.ftsuite.com/4ODS/Interface.py.html
#
"""
Implements the Interface meta-data 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
"""

from Ft.Ods.MetaData import Type
from Ft.Ods.MetaData import DefiningScope
from Ft.Ods.MetaData import MetaKind
from Ft.Ods.StorageManager.Adapters import Constants
from Ft.Ods import PersistentObject, Exception
td = PersistentObject.TupleDefinitions


class Interface(Type.Type,DefiningScope.DefiningScope):


    class ParameterSpec:
        def __init__(self,param_name,param_mode,param_type):
            self.param_mode = param_mode
            self.param_name = param_name
            self.param_type = param_type

    BadParameter = Exception.BadParameter
    BadRelationship = Exception.BadRelationship
        

    def __init__(self,db,data, meta_kind=None):
        if meta_kind is None:
            meta_kind = MetaKind.mk_interface
        Type.Type.__init__(self,db,data,meta_kind)
        DefiningScope.DefiningScope.__init__(self)

    def add_inherits(self, inherits, inverse=1):
        self._4ods_addRelationship('inherits',Interface,'derives','add',inherits,inverse)
    form_inherits = add_inherits

    def remove_inherits(self, inherits, inverse=1):
        self._4ods_removeRelationship('inherits','derives','remove',inherits,inverse)
    drop_inherits = remove_inherits

    #relationship derives
    def add_derives(self, derives, inverse=1):
        self._4ods_addRelationship('derives',Interface,'inherits','add',derives,inverse)
    form_derives = add_derives

    def remove_derives(self, derives, inverse=1):
        self._4ods_removeRelationship('derives','inherits','remove',derives,inverse)
    drop_derives = remove_derives

    def add_attribute(self,attr_name,attr_type):
        from Ft.Ods.MetaData import Attribute
        a = Attribute.Attribute(self._db,None)
        a.name = attr_name
        a.form_type(attr_type)
        self.bind(attr_name,a)
        return a

    #NOTE!  Changed from the spec
    def add_relationship(self,rel_name,rel_type,target,inverse_name,inverse_type):
        from Ft.Ods.MetaData import Relationship
        ourR = Relationship.Relationship(self._db,None)
        ourR.name = rel_name
        ourR.form_type(rel_type)

        otherR = Relationship.Relationship(self._db,None)
        otherR.name = inverse_name
        otherR.form_type(inverse_type)

        ourR.form_traversal(otherR)
        self.bind(rel_name,ourR)
        target.bind(inverse_name,otherR)


        return ourR

    def add_operation(self,op_name,op_result,op_params):
        from Ft.Ods.MetaData import Operation
        o = Operation.Operation(self._db,None)
        o.name = op_name
        if op_result:
            o.form_result(op_result)
        if op_params:
            for op in op_params:
                o.add_signature(op)
        self.bind(op_name,o)
        return o

    def remove_attribute(self,a):
        if not a._4ods_checkRemove():
            raise DefiningScope.CannotRemove(reason='Failed Remove Check')
        self.remove_defines(a)

    def remove_relationship(self,r):
        if not r._4ods_checkRemove():
            raise DefiningScope.CannotRemove(reason='Failed Remove Check')
        self.remove_defines(r)

    def remove_operation(self,o):
        if not o._4ods_checkRemove():
            raise DefiningScope.CannotRemove(reason='Failed Remove Check')
        self.remove_defines(o)

    def _4ods_getOdmgType(self):
        return Constants.Types.POBJECT

    def _4ods_getOdl(self,indent):
        st = indent + 'interface %s ' % self.name

        if self.inherits:
            st = st + ": "
        for i in self.inherits:
            st = st + "%s," % i.absolute_name()

        st = st[:-1] + ' {\n'
        for d in self.defines:
            st = st + d._4ods_getOdl(indent + '  ')
            st = st + "\n"
        st = st + indent + '};\n'
        return st

    def _4ods_checkRemove(self):
        return 1


    def _4ods_findTypePath(self,object):
        for d in self.defines:
            if d == object:
                return [self,object]
            res = d._4ods_findTypePath(object)
            if res:
                return [self] + res
        return []

    def _4ods_getGeneratedMetaClasses(self,found,checked):
        if self in checked: return
        checked.append(self)
        found.append(self)
        for d in self.defines:
            d._4ods_getGeneratedMetaClasses(found,checked)


    _tupleNames =  (('inherits',),('derives',))

    _tupleDefinitions = {'inherits':{td.TYPE:Constants.Types.SET_COLLECTION,
                                     td.READONLY:1,
                                     td.RELATIONSHIP:1,
                                     td.COLLECTION_SUBTYPE:Constants.Types.ROBJECT,
                                     },
                         'derives':{td.TYPE:Constants.Types.SET_COLLECTION,
                                     td.READONLY:1,
                                     td.RELATIONSHIP:1,
                                     td.COLLECTION_SUBTYPE:Constants.Types.ROBJECT,
                                     },
                         }
    _localExtents = ()
