"""
    DataSourceReader
    ================

Allow objects to read data from (almost) any kind of data source.
"""
# $Id: DataSourceReader.py,v 1.3 2002/08/18 15:30:26 adrian Exp $
#
# $Log: DataSourceReader.py,v $
# Revision 1.3  2002/08/18 15:30:26  adrian
# *** empty log message ***
#
# Revision 1.2  2002/08/18 15:27:16  adrian
# Changed (Fixed) ZDC.
# * It now uses temporary, in memory, indexes
# * It now reverses joins to ensure consistancy
# * It now generates "virtual SQL" so you can see what you are asking.
#
# Revision 1.1.1.1  2002/02/03 17:07:16  root
#
#
# Revision 1.2  2001/10/21 15:03:36  adrian
# no message
#
#
__version__ = '$Revision: 1.3 $'[11:-2]

class DataSourceReader:
    """ Read data from any datasource """

    DSR_data_source_id = ''
    DSR_cache = None
    DSR_columns = ()
    DSR_data_dictionary = ()

    def __init__(self, acquirer=None, datasource=''):
        """ If this is used stand-alone """
        self._setDataSource(acquirer=acquirer, datasource=datasource)

    def _setDataSource(self, acquirer=None, datasource=''):
        """ Set the data source ID. If this is an object, get it's ID """
        self.DSR_data_source_id = ''
        self.DSR_cache = None
        self.DSR_columns = ()
        self.DSR_data_dictionary = ()
        if not acquirer:
            acquirer = self
        if type(datasource) == type(''):
            self.DSR_data_source_id = datasource
            if hasattr(acquirer, datasource):
                data = getattr(acquirer, self.DSR_data_source_id)
            else:
                data = None
        elif type(datasource) == type(()) or type(datasource) == type([]):
            self.DSR_data_source_id = '__cache__'
            data = datasource
            self.DSR_cache = datasource
        else:
            self.DSR_data_source_id = datasource.id
            if callable(self.DSR_data_source_id):
                self.DSR_data_source_id = self.DSR_data_source_id()
            data = datasource
        if callable(data):
            data = data()
        if self.DSR_data_source_id == '__cache__':
            self.DSR_columns = tuple(data[0].keys())
            self.DSR_data_dictionary = []
            for columnName in self.DSR_columns:
                dde = {'name': '%s' % columnName}
                v = data[0][columnName]
                if type(v) == type(''):
                    dde['type'] = 's'
                if type(v) == type(1):
                    dde['type'] = 'i'
                if type(v) == type(1l):
                    dde['type'] = 'l'
                if type(v) == type(1.1):
                    dde['type'] = 'n'
                else:
                    dde['type'] = 'unknown'
                self.DSR_data_dictionary.append(dde)
            self.DSR_data_dictionary = tuple(self.DSR_data_dictionary)
        else:
            self.DSR_columns = tuple(data.names())
            self.DSR_data_dictionary = data.data_dictionary()

    def _getColumnList(self):
        """ Get the (ordered) list of columns from the data source """
        return self.DSR_columns

    def _getDataDictionary(self):
        """ Get the (unordered) data dictionary from the data source """
        return self.DSR_data_dictionary

    def _getData(self, acquirer=None):
        """ Return all the records from the dataset """
        if not acquirer:
            acquirer = self
        if self.DSR_data_source_id == '__cache__':
            data = self.DSR_cache
        else:
            data = getattr(acquirer, self.DSR_data_source_id)
        if callable(data):
            data = data()
        try:
# For TinyTable
            data = data.dictionaries()
        except:
# For ZSQLMethod (Incl. ZVisualQuery)
            pass
        newData = []
        for row in data:
            newRow = {}
            for column in self.DSR_columns:
                newRow[column] = row[column]
            newData.append(newRow)
        return newData
