#
# <one line to give the library's name and an idea of what it does.>
# Copyright (C) 2014  <copyright holder> <email>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program 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 General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 
#

import corpus2
import filterinterface

class POSFilter(filterinterface.FilterInterface):
  """!
  The idea of this class is based on filtering tokens using parts of speech.

  The class overrides the inherited method accept_token_as_node in the way that 
  it accepts only one argument: token. A tagset is stored as an attribute of the
  class. The accept_token_as_node method preserves only a token whose POS exists
  in a provided list of parts of speech. All parts of speech are accepted by
  default.
  """

  def __init__(self, tagset, options):
    """!
    Create the POS filter by setting the tagset and the list of accepted pos.

    Constructor sets the tagset as the attribute of the class. The list of 
    accepted POS should be in options (as 'accepted_pos'). Additionally, the
    mask of parts of speech is built based on the given tagset.

    @param tagset the desirable tagset.
    @type tagset: corpus2.Tagset
    @param options it should contain 'accepted_pos' that is the list of parts
      of speech (according to the tagset) which will be accepted in the filter. 
      POS that don't belong to this list will be skipped. The default value has
      been described above.
    @param options: dict(str: str)
    """
    super(POSFilter, self).__init__(options)
    self.tagset = tagset
    self._accept_pos = options.get('accepted_pos')
    # If accepted POS are read from the config then this is a string
    # Split it in order to get a list
    if isinstance(self._accept_pos, (str, unicode)):
      self._accept_pos = self._accept_pos.split()
    self._full_pos_mask = corpus2.get_attribute_mask(self.tagset, '')

  def accept_token_as_node(self, token):
    """!
    Return True if the POS of the token is accepted, False otherwise.

    For the given token the method checks its part of speech and returns True 
    if the POS belongs to the defined list of accepted tokens, False otherwise.
    
    @param token the token object from a text to be checked.
    @type token: corpus2.Token

    @return True if the token is accepted, False otherwise.
    @rtype: bool
    """
    lexem = token.get_preferred_lexeme(self.tagset)
    tag_pos_mask = lexem.tag().get_masked(self._full_pos_mask)
    tag_str = self.tagset.tag_to_symbol_string(tag_pos_mask)
    return tag_str in self._accept_pos


class POSInterpFilter(filterinterface.FilterInterface):
  """!
  A very similar filter to the POSFilter but this it returns only these tokens 
  whose part of speech is NOT 'interp'. However, the unacceptable POS may be
  defined as one desires.

  The class overrides the accept_token_as_node method in the way the POSFilter 
  class does.
  """

  def __init__(self, tagset, options):
    """!
    Create the POS filter by setting the tagset and the unacceptable POS.

    Constructor sets the tagset as the attribute of the class. The options 
    dictionary should contain 'interp_str' entry which defines the unacceptable
    POS. Otherwise it will be set to 'interp'. Additionally, the mask of parts 
    of speech is built based on the given tagset and the unacceptable POS.

    @param tagset the desirable tagset.
    @type tagset: corpus2.Tagset
    @param options it should contain 'interp_str' that is the unacceptable POS
      (according to the tagset) which will be rejected by the filter. 
      The default value is 'interp'.
    @param options: dict(str: str)
    """
    super(POSInterpFilter, self).__init__(options)
    self.tagset = tagset
    self._full_pos_mask = corpus2.get_attribute_mask(self.tagset, '')
    self._interp_mask = tagset.parse_symbol(options.get('interp_str'))

  def accept_token_as_node(self, token):
    """!
    Return True if the POS of the token is accepted, False otherwise.

    For the given token the method checks its part of speech and returns True 
    if the POS is different than the unacceptable POS, False otherwise.
    
    @param token the token object from a text to be checked.
    @type token: corpus2.Token

    @return True if the token is accepted, False otherwise.
    @rtype: bool
    """
    token_interp_mask = \
      token.get_preferred_lexeme(self.tagset).\
        tag().get_masked(self._interp_mask)
    return not token_interp_mask == self._interp_mask