########################################################################
#
# File Name:            Query.py
#
# Documentation:        http://docs.4suite.org/4Rdf/Inference/Query.py.html
#
"""

WWW: http://4suite.org/4RDF         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.Rdf.Statement import Statement
import Common
class Query:
    def __init__(self, id_,arguments):
        self.id = id_
        self.arguments = arguments
        self.type = Common.ArgumentTypes.QUERY
        return
    def execute(self,infEng,context):
        return self.query(infEng,context)

    def _4rdf_dump(self,indent=0):

        iStr = "\t" * indent
        rt = iStr + "<ril:query id='%s'>\n" % self.id
        for arg in self.arguments:
            rt = rt + arg._4rdf_dump(indent+1)
        rt = rt + iStr + '</ril:query>\n'
        return rt

class SingleQuery(Query):
    '''
    Complete and RDF triple with the argument as the subject and the object ignored
    '''

    def query(self, infEng, context):
        if self.arguments[0].type == Common.ArgumentTypes.SKOLEM_VARIABLE and self.arguments[0].execute(infEng,context) is None:
            #All instances of this predicate
            triples = infEng.complete('', self.id, '')
            rt = map(lambda x: (x.subject,x.predicate,x.object), triples)
            return rt
        #This is a filter based on the arguments
        args = self.arguments[0].execute(infEng,context)
        rt = []
        for arg in args:
            triples = infEng.complete(arg,self.id,'')
            rt = rt + map(lambda x:(x.subject,x.predicate,x.object),triples)
        return rt


class DualQuery(Query):
    '''
    A Complete with 2 arguments
    '''

    def query(self, infEng, context):

        #Use Cases
        #Foo($X,$X)
        #Foo($X,$Y)
        #Foo($X,"")
        #Foo("",$X)
        #Foo("","")

        arg0 = self.arguments[0]
        arg1 = self.arguments[1]
        args0 = arg0.execute(infEng,context)
        args1 = arg1.execute(infEng,context)
        
        results = []

        if arg0.type == Common.ArgumentTypes.SKOLEM_VARIABLE and args0 is None:
            #Cases 1-3
            if arg1.type == Common.ArgumentTypes.SKOLEM_VARIABLE and args0 is None:
                #Cases 1-2
                results = map(lambda x:(x.subject,x.predicate,x.object),infEng.complete('',self.id,''))
                if arg0.name == arg1.name:
                    #Case 1
                    results = filter(lambda x:x[0] == x[2],results)
            else:
                #Case 3
                for arg in args1:
                    triples = infEng.complete('',self.id,arg)
                    results = results + map(lambda x:(x.subject,x.predicate,x.object),triples)
        elif arg1.type == Common.ArgumentTypes.SKOLEM_VARIABLE and args1 is None:
            #Case 4
            for arg in args0:
                triples = infEng.complete(arg,self.id,'')
                results = results + map(lambda x:(x.subject,x.predicate,x.object),triples)
        else:
            #Case 5
            for a1 in args0:
                for a2 in args1:
                    if infEng.contains(Statement(a1,self.id,a2)):
                        results.append((a1,self.id,a2))
        return results

