# -*- coding: utf8 -*-
'''
DATA TYPES MODULE
********************
*** TYPES MODULE ***
********************
$RCSfile: typeconverter.py,v $
$Revision: 911 $
$Author: markus $
$Date: 2008-04-30 23:52:39 +0200 (Mi, 30. Apr 2008) $

Contains Classes to convert types/values from/into database, XML and Python types/values
'''

from types                          import *
from string                         import replace
from datetime                       import datetime
from biocase.wrapper.errorclasses   import *
from biocase.wrapper.sql.base       import sqlBase
import iso8601
import logging
log=logging.getLogger("pywrapper.typeconverter")



# ************************
# ***  GENERAL FUNCTIONS
# ************************

def reduceFakeFloats2Int(x):
    # check if its a float like integer
    while x[-1] == "0" and (x.find('.') or x.find(",")):
        x = x[:-1]
    if x[-1] in ['.', ","]:
        x = x[:-1]
    return x

# ************************
# ***  DB-ATTRIBUTE CLASS
# ************************

class DBAttributeClass:
    '''Class to store all information about one attribute of a DB.
    Formerly a tuple (DBAttrObj) was used for this.
    '''
    def __init__(self):
        self.table = None
        self.attr  = None
        # maybe one fo the following:
        # int float date text
        self.type  = 'text'
        # if set to 1 no search is allowed on this attribute:
        self.nosearch = 0
        # only needed for retrieving data from record sets:
        self.rsindex = None
        
    def _debug_repr(self):
        return "(DBAttributeInstance: table=%s, attribute=%s, DBtype=%s, RSindex=%s, nosearch=%i)"%(self.table, self.attr, self.type, str(self.rsindex), self.nosearch)

    def __repr__(self):
        return self.getHumanString()

    def getHumanString(self):
        nosearch = ''
        if self.nosearch:
            nosearch=' nosearch'
        return "%s.%s(%s)%s"%(self.table, self.attr, self.type, nosearch)

    def toSimpleString(self):
        return "%s(%s)"%(self.attr, self.type)

# ************************
# ***  DB-VALUE CLASS
# ************************

class DBValueClass:
    '''Class to store all information about one value used in SQL.
    Formerly a tuple (SQL Value tuple) was used for this.
    '''
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def __init__(self, value=None, typ=None):
        if typ == None:
            typ='text'
        self.value = value
        self.type  = typ
        
    def __repr__(self):
        return "DBVal(VAL=%s TYPE=%s)" % (self.value,self.type)

# ********************************
# ***  DB-TYPES TRANSFORMER CLASS
# ********************************

class DBtransformerClass:
    '''Converts data that is used for building SQL queries.
    The correct Python data-types will be produced for a given DB type.
    x has to be a tuple like this: (value/type).
    Maybe overriden by any db-module, therefore all type specific routines are kept seperate.
    Accepted types according to the CMF schema are:
    int, float, date, string, unicode
    '''
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def __init__(self, encoding='latin-1'):
        self.encoding = encoding
                # return SQL string with placeholders and the parameters seperately.
        # call function "integrateParametersInSQLString" to integrate parameters into SQL string
        self.integrateParameters = 0

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def transformPythonVal2DB(self, x):
        '''Converts data that is used for building SQL queries.
        The correct Python data-types will be produced for a given DB type.
        x has to be a DBValueClass object.'''
        if x.value == None:
            x.value = ''
        elif x.type in ('text','unicode'):
            x.value = self.makeUnicode(x.value)
        elif x.type == 'date':
            x.value = self.makeDate(x.value)
        elif x.type in ('integer', 'int'):
            x.value = self.makeInteger(x.value)
        elif x.type == 'float':
            x.value = self.makeFloat(x.value)
        return x.value

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def replaceWildcardAndEscapeCharacters(self, x):
        for old,new in sqlBase.escape.items():
            x = x.replace(old,new)
        return replace(x,'*', sqlBase.templates['wildcard'])
    
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def makeString(self, x):
        # convert to 8bit DB encoding
        try:
            return self.replaceWildcardAndEscapeCharacters(x.encode(self.encoding))
        except:
            return ''
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def makeUnicode(self, x):
        return  self.replaceWildcardAndEscapeCharacters(unicode(x))

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def makeInteger(self, x):
        # convert to integer
        return int(x)
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def makeFloat(self, x):
        # convert to float
        return float(x)
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def makeDate(self, x):
        # convert from datetime or date-string to ISO 8601
        # http://www.w3.org/TR/xmlschema-2/#date
        # YYYY-MM-DD
        if type(x) == datetime:
            # datetime object
            d = x
        elif type(x) in (type('k'), type(u'?')):
            x = x.strip()
            tmp = x
            # only date needed
            if len(x) > 10:
                x = x[:10]
            try:
                d = iso8601.parse_date(x)
            except:
                raise wrongTypeForDBError(x,typ)
        else:
            raise wrongTypeForDBError(x,typ)
        return d.isoformat()[:10]


    # ---------------------------
    
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def integrateParametersInSQLString(self):
        '''Use the different functions below to transform Python values into DB values.
        These functions starting with _make transform the values into a SQL suitable string.
        This may result in an error in the database later on, because most drivers do not permit unicode strings.
        Try to convert them into 8bit encodings. may be you are lucky.
        '''
        self.integrateParameters = 1
        DBtransformerClass.makeInteger = self._makeInteger
        DBtransformerClass.makeFloat = self._makeFloat
        DBtransformerClass.makeDate = self._makeDate
        DBtransformerClass.makeString = self._makeString
        DBtransformerClass.makeUnicode = self._makeUnicode
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _makeInteger(self, x):
        # number in DB
        try:
            x = int(x)
        except:
            #return 'NULL'
            raise SQLgenerationError()
        return sqlBase.templates['number'].replace('#1', str(x))
            
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _makeFloat(self, x):
        try:
            x = float(x)
        except:
            #return 'NULL'
            raise SQLgenerationError()
        return sqlBase.templates['number'].replace('#1', str(x))
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _makeDate(self, x):
        # date/time in DB
        x = unicode(x)
        # replace escape characters
        for old,new in sqlBase.escape.items():
            x = x.replace(old, new)
        return sqlBase.templates['string'].replace('#1', x)
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _makeString(self, x):
        # string in DB
        x = unicode(x)
        # replace escape characters
        x = self.replaceWildcardAndEscapeCharacters( x )
        x = sqlBase.templates['string'].replace('#1', x)
        # only 8bit allowed
        return x.encode(self.encoding)

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def _makeUnicode(self, x):
        # string in DB
        x = unicode(x)
        # replace escape characters
        x = self.replaceWildcardAndEscapeCharacters( x )
        return sqlBase.templates['string'].replace('#1', x)


        
        


# **********************
# ***  XML-TYPES MODULE
# **********************

# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
class XMLtransformerClass:
    '''Collection of functions to transform values into correct UTF-8 XML values.
    Used as a base class for the CMF output class.'''
    def __init__(self):
        # store reference to log object
                # default values if used without CMF class.
        # see cmf_element class for details
        self.Type = 'string'
        self.Name = None
        self.Voc   = []
        self.VocDB = []
        self.VocDict = None
        
    def wrongXMLType(self, value):
        '''For logging failed data convertions without raising an error.'''
        if self.Name == None:
            elem = 'unknown'
        else:
            elem = "'%s'"%(self.Name)
        log.warn("Unable to convert the DB value '%s' into XML type %s for Element %s" %(value, self.Type, elem))
        
    def wrongXMLContrVoc(self, value):
        '''Logging of values not contained in the controlled vocabulary as specified in the XML schema.'''
        if self.Name == None:
            elem = 'unknown'
        else:
            elem = "'%s'"%(self.Name)
        log.warn("The DB value '%s' is not contained in the vocabulary of the XML element %s. Element was dropped." %(value, elem))

    def transformDBVal2XML(self, x, encoding='latin-1', stripWhitespace=True):
        '''encodes a database retrieved value into unicode and checks if string for desired XML type is correct.'''
        #
        # convert data into unicode string
        #
        # copy of x in case we have some special objects like date.
        # and for potential error output:
        xCopy = x
        # convert x into unicode string as most values are unicode strings (taken from XML requests):
        if x == None:
            pass
        elif type(x) == UnicodeType:
            # already unicode
            pass
        elif type(x) == StringType:
            # convert from 8 bit string to unicode
            try:
                x = unicode(x, encoding)
            except LookupError:
                raise unknownEncodingError(encoding)
            except:
                # only log error - dont abort query
                try:
                    raise unknownTypeError(x)
                except:
                    pass
                try:
                    x = str(x)
                except:
                    x = u'?'
        elif type(x) in (IntType, LongType):
            # convert integers
            x = unicode(x)
        elif type(x) == FloatType:
            # convert floats
            x = reduceFakeFloats2Int(unicode(x))
        elif type(x) == datetime:
            # convert datetime types to unicode ISO 8601 string:
            x = unicode(x.isoformat())
        else:
            # blind encoding from unknown data type
            try:
                x = unicode(x)
            except:
                # only log error - dont abort query
                try:
                    raise unknownTypeError(x)
                except:
                    pass
        # remove "empty" strings
        if stripWhitespace and x <> None and x.strip() == '':
            x = None
        #
        # check for XML types:
        #
        if x <> None:
            if self.Type == None:
                self.Type = 'string'
            self.Type = self.Type.lower()
            if self.Type == 'normalizedstring':
                # do not contain the carriage return (#xD), line feed (#xA) nor tab (#x9) characters
                x = x.replace(chr(13),' ')
                x = x.replace(chr(10),' ')
                x = x.replace(chr(9),' ')
            elif self.Type in ('token','nmtoken'):
                # do not contain the line feed (#xA) nor tab (#x9) characters, that have no leading or trailing spaces (#x20) and that have no internal sequences of two or more spaces
                x = x.strip()
                x = x.replace(chr(10),' ')
                x = x.replace(chr(9),' ')
                while x.find('  ') <> -1:
                    x = x.replace('  ',' ')
            elif self.Type == 'anyuri':
                # anyURI value can be absolute or relative, and may have an optional fragment identifier (i.e., it may be a URI Reference)
                # no validation is done as proposed by the W3C:
                # http://www.w3.org/TR/xmlschema-2/#anyURI
                # "Each URI scheme imposes specialized syntax rules for URIs in that scheme, including restrictions on the syntax of allowed fragement identifiers. Because it is impractical for processors to check that a value is a context-appropriate URI reference, this specification follows the lead of [RFC 2396] (as amended by [RFC 2732]) in this matter: such rules and restrictions are not part of type validity and are not checked by ?minimally conforming? processors. Thus in practice the above definition imposes only very modest obligations on ?minimally conforming? processors."
                x = x.strip()
                x = x.replace(chr(13),' ')
                x = x.replace(chr(10),' ')
                x = x.replace(chr(9),' ')
                # HACK: set x to None if it is only http:// as delivered by nodit for empty fields
                if x.lower() == 'http://':
                    x = None
            elif self.Type in ('id','idref','idrefs'):
                if len(x) > 2 and x[:2] != 'ID':
                    x = 'ID'+x
            elif self.Type in ('int','integer','long','short'):
                x = x.strip()
                # check if its negative
                if not x.isdigit():
                    if len(x) > 0 and x[0] == '-':
                        digits = x[1:].strip()
                        if not digits.isdigit():
                            self.wrongXMLType(xCopy)
                            x = None
                        else:
                            x = '-'+digits
                    else:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type in ('unsignedint','unsignedlong','unsignedshort'):
                x = x.strip()
                if not x.isdigit():
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'nonpositiveinteger':
                x = x.strip()
                if len(x) > 0 and x[0] == '-':
                    digits = x[1:].strip()
                    if digits.isdigit():
                        x = '-'+digits
                    else:
                        self.wrongXMLType(xCopy)
                        x = None
                elif x == '0':
                    pass
                else:
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'nonnegativeinteger':
                x = x.strip()
                try:
                    x=str(int(float(x)))
                except:
                    pass
                if not x.isdigit():
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'positiveinteger':
                x = x.strip()
                if not x.isdigit() or x == '0':
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'negativeinteger':
                x = x.strip()
                if len(x) > 0 and x[0] == '-':
                    digits = x[1:].strip()
                    if digits.isdigit():
                        x = '-'+digits
                    else:
                        self.wrongXMLType(xCopy)
                        x = None
                else:
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'hexbinary':
                # 0FB7 
                x = x.strip()
                # check copy of x
                y = x.lower()
                y = y.replace('a','')
                y = y.replace('b','')
                y = y.replace('c','')
                y = y.replace('d','')
                y = y.replace('e','')
                y = y.replace('f','')
                if y.isdigit():
                    # set trailing 0 if uneven numbers
                    (a,b) = divmod(len(x),2)
                    if b > 0:
                        x = '0'+x
                    x = x.upper()
                else:
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type in ('float','double','decimal'):
                # convert commas to dots
                x = x.strip()
                if x.count(',') == 1 and x.count('.') == 0:
                    x = x.replace(',','.')
                if x.count('.') > 1:
                    self.wrongXMLType(xCopy)
                    x = None
                else:
                    # check copy of x
                    y = x
                    y = y.replace('.','')
                    if not y.isdigit():
                        if y[0] == '-':
                            digits = y[1:].strip()
                            if not digits.isdigit():
                                self.wrongXMLType(xCopy)
                                x = None
                            else:
                                x = '-' + x[1:].strip()
                        else:
                            self.wrongXMLType(xCopy)
                            x = None
            elif self.Type == 'boolean':
                # true, false   1, 0 
                x = x.strip().lower()
                if x not in ('false','true','0','1'):
                    self.wrongXMLType(xCopy)
                    x = None
            elif self.Type == 'date':
                # http://www.w3.org/TR/xmlschema-2/#date
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # YYYY-MM-DD
                # also allows date input with .,: instead of -
                if type(xCopy) == datetime:
                    x = unicode(xCopy.isoformat())[:10]
                else:
                    x = x.strip()
                    # ignore time
                    x = x[:10]
                    if x.count('.') == 2:
                        # YYYY.MM.DD -> YYYY-MM-DD
                        x = x.replace('.','-')
                    elif x.count(',') == 2:
                        # YYYY,MM,DD -> YYYY-MM-DD
                        x = x.replace(',','-')
                    elif x.count(':') == 2:
                        # YYYY:MM:DD -> YYYY-MM-DD
                        x = x.replace(':','-')
                    try:
                        d = iso8601.parse_date(x)
                        x = unicode(d.isoformat[:10])
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type == 'gyearmonth':
                # http://www.w3.org/TR/xmlschema-2/#gYearMonth
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # YYYY-MM
                # also allows date input with .,: instead of -
                if type(xCopy) == datetime:
                    x = unicode(xCopy.isoformat())[:7]
                else:
                    x = x.strip()
                    x = x[:7]
                    x = x.replace('.','-')
                    x = x.replace(',','-')
                    x = x.replace(':','-')
                    try:
                        d = iso8601.parse_date(x)
                        x = unicode(d.isoformat)[:7]
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type == 'gyear':
                # http://www.w3.org/TR/xmlschema-2/#gyear
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # YYYY
                if type(xCopy) == datetime:
                    x = unicode(xCopy.isoformat())[:4]
                else:
                    x = x.strip()
                    x = x[:4]
                    try:
                        d = iso8601.parse_date(x)
                        x = unicode(d.isoformat())[:4]
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type == 'gmonthday':
                # http://www.w3.org/TR/xmlschema-2/#gmonthday
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # --MM-DD
                # also allows date input with .,: instead of -
                if type(xCopy) == datetime:
                    x = '--'+unicode(xCopy.isoformat())[5:10]
                else:
                    x = x.strip()
                    # ignore time
                    x = x[:10]
                    x = x.replace('.','-')
                    x = x.replace(',','-')
                    x = x.replace(':','-')
                    try:
                        if len(x) < 10:
                            # not a full date. maybe only the monthday ?
                            while x[0] == '-':
                                x = x[1:]
                            try:
                                (m,d) = x.split('-')
                                if (m.isdigit() and 0 < int(m) and int(m) < 13) and (d.isdigit() and 0 < int(d) and int(d) < 32):
                                    x = '--'+x
                                else:   
                                    self.wrongXMLType(xCopy)
                                    x = None
                            except:
                                self.wrongXMLType(xCopy)
                                x = None
                        else:
                            # try to parse full date
                            d = iso8601.parse_date(x)
                            x = '--'+unicode(d.isoformat())[5:10]
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type == 'gday':
                # http://www.w3.org/TR/xmlschema-2/#gday
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # ---DD
                # also allows date input with .,: instead of -
                if type(xCopy) == datetime:
                    x = '---'+unicode(xCopy.isoformat())[8:10]
                else:
                    x = x.strip()
                    # ignore time
                    x = x[:10]
                    x = x.replace('.','-')
                    x = x.replace(',','-')
                    x = x.replace(':','-')
                    try:
                        if len(x) < 10:
                            # not a full date. maybe only the day ?
                            if x[0:3] == '---':
                                x = x[3:]
                            if x.isdigit() and 0 < int(x) and int(x) < 32:
                                if int(x) < 10 and len(x) == 1:
                                    x = '0'+x
                                x = '---'+x
                            else:
                                self.wrongXMLType(xCopy)
                                x = None
                        else:
                            # try to parse full date
                            d = iso8601.parse_date(x)
                            x = '---'+unicode(d.isoformat())[8:10]
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            elif self.Type == 'gmonth':
                # http://www.w3.org/TR/xmlschema-2/#gmonth
                # Gregorian calendar dates as defined in ? 5.2.1 of [ISO 8601].
                # --MM--
                # also allows date input with .,: instead of -
                if type(xCopy) == datetime:
                    x = '--'+unicode(xCopy.isoformat())[5:7]+'--'
                else:
                    x = x.strip()
                    # ignore time
                    x = x[:10]
                    x = x.replace('.','-')
                    x = x.replace(',','-')
                    x = x.replace(':','-')
                    try:
                        if len(x) < 10:
                            # not a full date. maybe only the month ?
                            if x[0:2] == '--':
                                x = x[2:]
                            while x[len(x)-1] == '-':
                                # remove trailing -
                                x = x[:len(x)-1]
                            if x.isdigit() and 0 < int(x) and int(x) < 13:
                                if int(x) < 10 and len(x) == 1:
                                    x = '0'+x
                                x = '--'+x+'--'
                            else:
                                self.wrongXMLType(xCopy)
                                x = None
                        else:
                            # try to parse full date
                            d = iso8601.parse_date(x)
                            x = '--'+unicode(d.isoformat())[5:7]+'--'
                    except:
                        self.wrongXMLType(xCopy)
                        x = None
            else:
                # treat it as a string:
                pass
            #
            # check for controlled vocabulary:
            #
            if len(self.Voc) > 0 and x <> None:
                # controlled vocabulary exists
                if self.VocDict == None:
                    # convertion dictionary does not yet exist. build it.
                    # make it case insensitive and additionally allow whitespace-stripped values
                    self.VocDict = {}
                    for v in self.Voc:
                        self.VocDict[v.lower()] = v
                        self.VocDict[v.lower().strip()] = v
                    # integrate VocDB translation. must be the same index as self.voc
                    i = 0
                    for vList in self.VocDB:
                        try:
                            if vList <> None and len(vList) > 0:
                                for v in vList:
                                    self.VocDict[v.lower()] = self.Voc[i]
                                    self.VocDict[v.lower().strip()] = self.Voc[i]
                        except:
                            # the dictionaries are out of sync !
                            log.warn("The controlled vocabulary Dictionaries for element %s are out of sync."%(self.Name))
                            pass
                        i += 1
                if self.VocDict.has_key(x.lower()):
                    # contr voc found
                    x = self.VocDict[x.lower()]
                elif self.VocDict.has_key(x.lower().strip()):
                    # stripped contr voc found
                    x = self.VocDict[x.lower().strip()]
                else:
                    # no matching contr voc found
                    self.wrongXMLContrVoc(xCopy)
                    x = None
            ######################
        return x





if __name__ ==  "__main__":
    # test type checking
    t = XMLtransformerClass()
    t.Type = 'string'
    t.Voc = ['---07','Bernd']
    d = datetime.now()
    print t.transformDBVal2XML('1999')
    print t.transformDBVal2XML('08-07 ')
    print t.transformDBVal2XML('---07 ')
    print t.transformDBVal2XML('--07 ')
    print t.transformDBVal2XML('bernd')
    print t.transformDBVal2XML('bernD')
    print t.transformDBVal2XML(' BERND ')
    print t.transformDBVal2XML('  2003-08-07 ')
    print t.transformDBVal2XML('  2003.08.07 ')
    print t.transformDBVal2XML(d)
    
    print reduceFakeFloats2Int("500.0")
            
