# Copyright (c) 2004 DoCoMo Euro-Labs GmbH (Munich, Germany).
# Copyright (c) 2001-2004 LOGILAB S.A. (Paris, FRANCE).
#
# http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""classes used to handle action elements


:version: $Revision:$ 
:author: Logilab  

:copyright:
  2001-2004 LOGILAB S.A. (Paris, FRANCE)
  
  2004 DoCoMo Euro-Labs GmbH (Munich, Germany)
  
:contact:
  http://www.logilab.fr/ -- mailto:contact@logilab.fr
  
  http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
"""

__revision__ = "$Id: ALAbstraction.py,v 1.36 2004/04/02 10:06:46 syt Exp $"
__docformat__ = "restructuredtext en"

from narval.public import AL_NS, NO_NS
from narval.element import DescriptionableMixin, ALElement, NSAttribute
from narval.xml_handlers import BaseXMLHandler, DescriptionHandler
from narval.prototype import Prototype, PrototypeHandler

class ALRecipeItem(DescriptionableMixin, ALElement):
    """abstract base class for narval recipe elements (i.e. recipes and actions)

    :type name: str
    :ivar name: the element's target name

    :type group: str
    :ivar group: the element's target group (i.e. module / cookbook)
    """
    
    name = NSAttribute(NO_NS, None, str, str)
    group = NSAttribute(NO_NS, None, str, str)
    from_file = NSAttribute(NO_NS, None, str, str)
    
    def get_identity(self):
        """returns the (group, name) attributes

        :rtype: tuple
        :return: element's group and name
        """
        return (self.group, self.name)

    def __repr__(self):
        return '<%s %s.%s eid=%s at %s>' % (self.__class__.__name__,
                                            self.group, self.name,
                                            self.eid, hex(abs(id(self))))
    


class ActionXMLHandler(BaseXMLHandler):
    """XML handler for action elements"""
    
    def __init__(self, elmt, ns_context, locator):
        super(ActionXMLHandler, self).__init__(elmt, ns_context, locator)
        self.sub_hdlr = None

    def start_element(self, name, attrs):
        """SAX callback: start a new xml node

        :type name: tuple
        :param name: the tag name as a tuple (uri, name)
        
        :type attrs: dict
        :param attrs:
          the node's attribute values, indexed by attribute's name as a tuple
          (uri, name)
        """
        prefix, local = name
        if prefix != AL_NS:
            log(LOG_ERR, 'Unknown prefix %s in action prototype, tag %s ignored',
                (prefix, local))
            return
        if local in ('input', 'output'):
            self.sub_hdlr = PrototypeHandler(self.elmt, self._ns_context,
                                             self._locator)
        if self.sub_hdlr:
            self.sub_hdlr.start_element(name, attrs)
        elif local == 'description':
            self.sub_hdlr = DescriptionHandler(self.elmt,
                                               attrs.get((None, 'lang'), 'en'))

    def end_element(self, name):
        """SAX callback: close a xml node

        :type name: tuple
        :param name: the tag name as a tuple (uri, name)
        """
        prefix, local = name
        if prefix != AL_NS:
            return
        if self.sub_hdlr is not None:
            try:
                self.sub_hdlr.end_element(name)
            except AttributeError:
                # description handler
                self.sub_hdlr = None
        if local in ('input', 'output') and prefix == AL_NS:
            self.sub_hdlr = None

    def characters(self, content):
        """SAX callback: get some (non empty) string

        :type content: unicode
        :param content: the non empty string to hold
        """
        if self.sub_hdlr is not None:
            self.sub_hdlr.characters(content)



class ActionElement(ALRecipeItem):
    """an action element : a reference to a python function

    :type func: str
    :ivar func: name of the actual python function in the module

    :type prototype: `narval.prototype.Prototype`
    :ivar prototype: the action's prototype, defining allowable inputs / ouputs
    """
    
    __xml_element__ = (AL_NS, 'action')
    __child_handler__ = ActionXMLHandler
    
    func = NSAttribute(NO_NS, None, str, str)
    
    def __init__(self):
        super(ActionElement, self).__init__()
        self.prototype = Prototype()
        
    def children_as_xml(self, encoding='UTF-8'):
        """return the xml representation of the children of an action

        :type encoding: str
        :param encoding:
          the encoding to use in the returned string, default to UTF-8
          
        :rtype: str
        :return: the action as an XML document
        """
        result = []
        descr_xml = self.description_as_xml(encoding)
        descr_xml and result.append(descr_xml)
        result.append(self.prototype.as_xml(encoding))
        return '\n'.join(result)

