########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Client/Commands/Rdf/Versa.py,v 1.16 2004/09/23 20:53:30 mbrown Exp $
"""
Implementation of '4ss rdf versa' command
(functions defined here are used by the Ft.Lib.CommandLine framework)

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

__doc__ = """This command performs a query on the combined user and
system RDF models, using the Versa query language for RDF. \
If necessary, you will be prompted first for credentials and access \
info to connect to the repository."""

import sys, cStringIO, codecs

from Ft.Lib import Uri
from Ft.Rdf._4versa import PrettyPrintResults, BASE_NS_MAP
from Ft.Rdf.Parsers.Versa import Util as VersaUtil
from Ft.Rdf.Statement import Statement
from Ft.Server.Client.Commands import CommandUtil
from Ft.Server.Common import Util


#DASHBOARD_NS = "http://chimezie.ogbuji.net/4ss/tools/dashboard/schema#"

#NSM_NSM = {'fres': 'http://xmlns.4suite.org/reserved'}

#PREFIXES = XPath.Compile("/fres:NsMappings/fres:NsMapping/Prefix/text()")
#URIS = XPath.Compile("/fres:NsMappings/fres:NsMapping/Uri/text()")


def Run(options, args):
    quiet = options.get('quiet')
    scope = options.get('scope')
    repo = CommandUtil.GetRepository(options, '4ss.rdf.versa')
    if repo is not None:
        try:
            model = repo.getModel()

            if not options.get('no-mapping-file'):
                ns_map = Util.GetUserNsMappings(repo, BASE_NS_MAP)
            else:
                ns_map = {}

            srcFile = options.get('query-file')
            #Read in the query
            if srcFile:
                stream = Uri.BASIC_RESOLVER.resolve(srcFile)
                con = FakeContext(model, ns_map, {}, scope=scope)
                result = VersaUtil.ProcessQueryFile(
                    stream, con, sys.stderr, queryFunction=QueryFunction
                    )
                stream = cStringIO.StringIO()
                enc, dec, rdr, wrtr = codecs.lookup("utf-8")
                stream = wrtr(stream)
                VersaUtil.ResultsToXml(result, stream)
                result = stream.getvalue()
            else:
                query = args.get('query', None)
                if not query:
                    sys.stderr.write("Enter Query: ")
                    query = sys.stdin.readline()
                    sys.stderr.write("\n")

                if not quiet:
                    sys.stderr.write("Executing Query:\n")
                    sys.stderr.write(query+'\n')

                if not quiet and ns_map:
                    sys.stderr.write("With the following namepace mappings:\n")
                    for name, value in ns_map.items():
                        sys.stderr.write("%s --> %s\n" % (name, value))

                result = model.versaQuery(query, ns_map)
            print result
        finally:
            try:
                repo.txRollback()
            except:
                pass

    return


def QueryFunction(query, context, scope=None):
    results = context.model.versaQueryRaw(query, context.nsMapping,
                                          context.varBindings, scope)
    return results


class FakeContext:
    """For accommodation of the interface of Ft.Rdf.Parsers.Versa.Util.ProcessQueryFile"""
    def __init__(self, model, nsMapping, varBindings, scope):
        self.model = model
        self.nsMapping = nsMapping
        self.varBindings = varBindings
        self.scope = scope
        return

    def clone(self):
        new_con = self.__class__(self.model, self.nsMapping.copy(),
                                 self.varBindings.copy(), self.scope)
        return new_con


def Register():

    from Ft.Lib.CommandLine import Options, Command, Arguments

    cmd = Command.Command('versa',
                          'Perform a Versa query',
                          '--query-file=',
                          __doc__,
                          function = Run,
                          arguments = [
                              Arguments.OptionalArgument('query',
                                                           'The query to perform.  Required if --file is not specified',
                                                           str),
                              ],
                          options = Options.Options([
                              Options.Option('q', 'quiet', 'Present no output except for errors or any result'),
                              Options.Option('f', 'query-file=', 'A file with the Versa query'),
                              Options.Option(None, 'no-mapping-file', "Do not use the user's namespace mapping file"),
                              Options.Option(None, 'scope=scope', 'a scope to restrict the query',),
                              ]),
                          fileName = __file__,
                          )
    return cmd

