# Copyright (c) 2000-2004 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# Copyright (c) 2004 DoCoMo Euro-Labs GmbH (Munich, Germany).
# http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
#
# 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
"""unit tests for narval modules.PyLogDB 

:version: $Revision:$  
:author: Logilab

:copyright:
  2000-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
"""

import unittest
import os
import tempfile
from os.path import abspath, dirname
        
from logilab.common import testlib

from narval.elements.base import URLElement
from narval.elements.rdf import RDFStatementElement, RDFRuleElement
from narval.actions.AlRDF import text_to_rule
from narval.actions.PyLogDB import *

class PylogDBTC(testlib.TestCase):

    def setUp(self):
        self.kb = URLElement()
        tempkb = tempfile.mktemp()
        file(tempkb, 'w').close()
        self.kb.address = 'file:%s' % tempkb

    def tearDown(self):
        os.remove(self.kb.address[5:])

    def test_act_unify(self):
        kb_file = self.kb
        # add some statements
        stmt = RDFStatementElement('Sylvain', 'works_for', 'Logilab')
        act_add_statements({'stmts': [stmt], 'kb': kb_file})
        stmt.subject = 'Alexandre'
        act_add_statements({'stmts': [stmt], 'kb': kb_file})
        stmt.subject = 'Antony'
        stmt.object = 'Docomo'
        act_add_statements({'stmts': [stmt], 'kb': kb_file})
        # add some rules
        rule = RDFRuleElement()
        X, Y = Var('X'), Var('Y')
        rule.statement = RDFStatementElement(X, 'is_paid_by', Y)
        rule.implies = [RDFStatementElement(X, 'works_for', Y)]
        act_add_rule({'rule': rule, 'kb': kb_file})
        rule = RDFRuleElement()
        X, Y = Var('X'), Var('Y')
        rule.statement = RDFStatementElement(X, 'emploie', Y)
        
        rule.implies = [RDFStatementElement(Y, 'works_for', X)]
        act_add_rule({'rule': rule, 'kb': kb_file})
        rule = RDFRuleElement()
        X, Y, Z = Var('X'), Var('Y'), Var('Z')
        rule.statement = RDFStatementElement(X, 'coleague', Y)
        rule.implies = [RDFStatementElement(X, 'works_for', Z),
                        RDFStatementElement(Y, 'works_for', Z)]
        act_add_rule({'rule': rule, 'kb': kb_file})

        statements = act_unify({'stmts': [RDFStatementElement(None, 'works_for', 'Logilab')],
                            'kb': kb_file})['stmts']
        self.assert_(statements)
        self.assert_(len(statements) == 2)

        statements = act_unify({'stmts': [RDFStatementElement('Sylvain', 'is_paid_by', None)],
                           'kb': kb_file})['stmts']
        self.assert_(statements, 'maybe the rules are not in the kb file, uncomment addition of rules in unittest')
        self.assert_(len(statements) == 1)
        
        statements =  act_unify({'stmts': [RDFStatementElement(None, 'coleague', 'Sylvain')],
                             'kb': kb_file})['stmts']
        self.assert_(statements)
        self.assert_(len(statements) == 2)
        statements =  act_unify({'stmts': [RDFStatementElement(None, 'emploie', 'Sylvain')],
                           'kb': kb_file})['stmts']
        self.assert_(statements)
        self.assert_(len(statements) == 1)

##     def test_syntactic_error(self):
##         pass

##     def test_is_a_narval(self):
##         kb = URLElement()
##         kb.address = 'file:%s/data/kb_is_narval.pl' % dirname(abspath(__file__))
##         self.assertEquals(is_a_narval('arthur', kb), False)
##         self.assertEquals(is_a_narval('gizmo', kb), True)
##         self.assertEquals(is_a_narval('name_not_exist', kb), False)

    def test_rule_1(self):
        rule_text = 'X grandchild Y if X child Z and Z child Y'
        statements = [('Etienne', 'child', 'Robert'),
                      ('Arthur', 'child', 'Etienne')]
        question = (None, 'grandchild', 'Robert')
        answer = ['Arthur','grandchild','Robert']
        self._test(rule_text, statements, question, answer)
        
    def test_rule_2(self):
        rule_text = 'X father Y if Y son X'
        statements = [('Arthur','son','Etienne' )]
        question =  ('Etienne', 'father', None)
        answer = ['Etienne', 'father', 'Arthur']
        self._test(rule_text, statements, question, answer)

    def test_rule_3(self):
        rule_text = 'X ne_mange_pas Z if X est Y, Y mange W, W n_est_pas Z'
        statements = [('paul', 'est', 'vegetarien'),
                      ('vegetarien', 'mange', 'legumes'),
                      ('legumes', 'n_est_pas', 'viandes')]
        question = ('paul', 'ne_mange_pas', None)
        answer = ['paul', 'ne_mange_pas', 'viandes']
        self._test(rule_text, statements, question, answer)

    def _test(self, rule_text, statements, question, answer):
        rule = text_to_rule(rule_text)
        act_add_rule({'rule': rule, 'kb': self.kb})
        for x, y, z in statements:
            stmt = RDFStatementElement(x, y, z)
            act_add_statements({'stmts': [stmt], 'kb': self.kb})
        results = act_unify({'stmts': [RDFStatementElement(*question)],
                         'kb': self.kb})['stmts']
        self.assertEquals(len(results), 1)
        self.assertEquals(answer, [results[0].subject,
                                   results[0].predicate,
                                   results[0].object])


        
if __name__ == '__main__':
    unittest.main()



