#!/usr/bin/python
""">> cassoap << command line query tool by Tamas Budavari <budavari@pha.jhu.edu>
Usage: cassoap.py [options] sqlfile(s)

Options:
        -s url    : URL of XML Web Service (default: pha)
        -q query  : specify query on the command line
        -o file   : set output file name (default: stdout)
        -h	  : show this message"""

import sys, os, getopt, string, httplib, xml.sax
from xml.sax.handler import ContentHandler
from xml.sax.saxutils import escape
            
class CasService:
    soap = """<?xml version="1.0" encoding="utf-8"?>\r
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"\r
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r
      <soap:Body>\r
        <GetStream xmlns="http://skyservice.pha.jhu.edu">\r
          <sqlcmd>%s</sqlcmd>\r
        </GetStream>\r
      </soap:Body>\r
    </soap:Envelope>\r
    """
    soapaction = "http://skyservice.pha.jhu.edu/GetStream"
    headers = {"Content-Type":"text/xml; charset=utf-8",
               "SOAPAction": soapaction}
    def __init__(self,host='skyservice.pha.jhu.edu',
                 path='/devel/CasService/CasService.asmx',
                 port=httplib.HTTP_PORT):
        self.host, self.path, self.port = host, path, port
        self.debuglevel = 0
    def GetStream(self,sqlcmd):
        body = self.soap % escape(sqlcmd)
        blen = len(body)
        requestor = httplib.HTTP(self.host, self.port)
        requestor.putrequest('POST', self.path)
        requestor.putheader('Host', self.host)
        requestor.putheader('Content-Type', 'text/xml; charset="utf-8"')
        requestor.putheader('Content-Length', str(blen))
        requestor.putheader('SOAPAction', self.soapaction)
        requestor.endheaders()
        requestor.send(body)
        (status_code, message, reply_headers) = requestor.getreply()
        if self.debuglevel > 0:
            print "** Status code:", status_code
            print "** Status message:", message
            print "** Headers:\n", reply_headers
        return requestor.getfile()

class CasStreamHandler(ContentHandler):
    """Crude extractor for CAS (stream) results
       print contents of <anyType> and newline at </CasItem>"""
    def __init__(self,ofp=None,gettype=0):
        try: self.write = ofp.write
        except: self.write = sys.stdout.write
        self.gettype = gettype
    def startDocument(self):
        self.in_item, self.item = 0, ''
    def startElement(self, name, attrs):
        if name == 'anyType':
            self.in_item, self.item = 1, ''
            if self.gettype: self.type = attrs.getValue('xsi:type')
        elif name == 'faultstring':
            self.exception = 1
            self.in_item, self.item = 1, ''
    def characters(self, ch):
        if self.in_item: self.item = self.item + ch
    def endElement(self, name):
        if name == 'anyType':
            self.write(self.item+' '); self.in_item = 0
            if self.gettype: self.write('('+self.type+') ')
        elif name == 'CasItem': self.write(os.linesep)
        elif name == 'faultstring':
            self.write('*** ERROR: ' + \
                       string.replace(self.item,'-->', os.linesep+'-->') + \
                       os.linesep)

def usage(status, msg=''):
    print __doc__
    if msg: print '-- ERROR: %s' % msg
    sys.exit(status)
    
def main(argv):
    "Parse command line and do it..."
    queries, outfile = [], sys.stdout
    try: optlist, args = getopt.getopt(argv[1:],'s:q:o:h?')
    except getopt.error, e: usage(1,e)
    # options
    for o,a in optlist:
        if   o=='-s': url = a
        elif o=='-q': queries.append(a)
        elif o=='-o': outfile = open(a,'w')
        else: usage(0)
    # Enqueue queries in files
    for fname in args:
        try: queries.append(open(fname).read())
        except IOError, e: usage(1,e)
    # Run all queries
    cas = CasService()
    parser = xml.sax.make_parser()
    parser.setContentHandler(CasStreamHandler(outfile))
    for qry in queries:
        res = cas.GetStream(qry)
        parser.parse(res)
    outfile.close()

# - - - - - - - - - - - - 
if __name__=='__main__':
    main(sys.argv)
# - - - - - - - - - - - -