########################################################################
#
# File Name:            Util.py
#
#
"""
Versa implementation utilities
WWW: http://4suite.org/4RDF        e-mail: support@4suite.org

Copyright 2002 Fourthought Inc, USA.
See  http://4suite.org/COPYRIGHT  for license and copyright information
"""

from Ft.Rdf import Model
DUMMY_MODEL = Model.Model(None)

def VersaQueryGivenContext(query, context, scope=None):
    from Ft.Rdf.Parsers import Versa
    context.scope = scope
    exp = Versa.Compile(query)
    results = exp.evaluate(context)
    return results


START = 1
MULTI_LINE_QUERY = 2
MULTI_LINE_VAR = 2


def ProcessQueryFile(src, inContext, logFile=None,
                     queryFunction=VersaQueryGivenContext, scope=None):
    from Ft.Rdf.Parsers import Versa
    con = inContext.clone()
    var_name = ""
    var_value = ""
    query = ""
    buffer = 0
    state = START
    for line in src.readlines():
        if not line.strip():continue
        if state == MULTI_LINE_VAR and not line[0].isspace():
            result = queryFunction(var_value, con)
            if logFile:
                logFile.write("Assigning variable %s using: %s\n"%(var_name, var_value))
            #FIXME: Support QNames
            con.varBindings[(None, var_name)] = result
        line = line.strip()
        if line[:5] == 'QUERY':
            query += line[6:]
            state = MULTI_LINE_QUERY
        elif line[:2] == 'NS':
            name, uri = line[3:].split("=")
            con.nsMapping[name] = uri
            logFile.write("Adding namespace mapping: %s --> %s\n"%(name, uri))
            state = START
        elif line[:3] == 'VAR':
            (var_name, var_value) = line[4:].split("=")
            state = MULTI_LINE_VAR
        elif state == MULTI_LINE_QUERY:
            query += line
        elif state == MULTI_LINE_VAR:
            var_value += line

    if logFile: logFile.write("Executing query: %s\n"%query)
    result = queryFunction(query, con, scope)
    return result


def ResultsToXml(result, stream, indent=u''):
    # By giving a namespace, the elements are created in the null-namespace
    if DataTypes.IsList(result):
        stream.write(indent)
        stream.write(u"<List>\n")
        for r in result:
            ResultsToXml(r, stream, indent+'  ')
        stream.write(indent)
        stream.write(u"</List>\n")
    elif DataTypes.IsSet(result):
        stream.write(indent)
        stream.write(u"<Set>\n")
        for r in DataTypes.ToList(result):
            ResultsToXml(r, stream, indent+u'  ')
        stream.write(indent)
        stream.write(u"</Set>\n")
    elif DataTypes.IsResource(result):
        stream.write(indent)
        if DUMMY_MODEL.isBnodeLabel(str(result)):
            stream.write(u"<BlankNode>%s</BlankNode>\n"%unicode(result))
        else:
            stream.write(u"<Resource>%s</Resource>\n"%unicode(result))
    elif DataTypes.IsString(result):
        stream.write(indent)
        stream.write(u"<String>%s</String>\n"%result)
    elif DataTypes.IsNumber(result):
        stream.write(indent)
        stream.write(u"<Number>%s</Number>\n"%unicode(result))
    elif DataTypes.IsBoolean(result):
        stream.write(indent)
        stream.write(u"<Boolean>%s</Boolean>\n"%unicode(result))
    else:
        raise Exception('Unknown Versa result type')
    return


import DataTypes

