"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/property/test/utest_property_type.py $
$Id: utest_property_type.py 28932 2006-10-12 20:29:05Z dbinger $
"""
from dulcinea.common import CommonTest
from dulcinea.material import get_material_db
from dulcinea.property import get_property_db
from dulcinea.property.errors import PropertyTypeError
from dulcinea.property.property_type import PropertyType
from dulcinea.physical_unit import get_standard_unit
from dulcinea.physical_value import PhysicalValue
from dulcinea.range_value import RangeValue
from sancho.utest import raises

class PropertyTypeTest (CommonTest):

    def _pre (self):
        CommonTest._pre(self)
        if get_property_db() is None:
            return
        self.plib = get_property_db()
        self.mdb = get_material_db()

    def check_int_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(PropertyType.ATOMIC,
                                                       PropertyType.INT)

        assert property_type1.is_atomic()
        assert property_type1.is_int()
        assert not property_type1.is_string()
        assert not property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert not property_type1.is_list()
        assert not property_type1.is_table()
        assert not property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(PropertyType.ATOMIC,
                                                       PropertyType.STRING)
        assert property_type2 is not property_type1
        property_type2 = self.plib.get_property_type(PropertyType.ATOMIC,
                                                       PropertyType.INT)
        assert property_type2 is property_type1

        property_type1.check_value(None)
        property_type1.check_value(10)
        property_type1.check_value(RangeValue(10, 20))
        raises(PropertyTypeError, property_type1.check_value, [10, 20])
        raises(PropertyTypeError, property_type1.check_value, 'hello')
        raises(PropertyTypeError, property_type1.check_value, ['hello', 'bye'])
        raises(AssertionError,
            self.plib.get_property_type,
            PropertyType.ATOMIC, PropertyType.INT, key_type=1)

    def check_string_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.STRING)

        assert property_type1.is_atomic()
        assert not property_type1.is_int()
        assert property_type1.is_string()
        assert not property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert not property_type1.is_list()
        assert not property_type1.is_table()
        assert not property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.INT)
        assert property_type2 is not property_type1
        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.STRING)
        assert property_type2 is property_type1

        property_type1.check_value(None)
        property_type1.check_value('hello')
        raises(PropertyTypeError, property_type1.check_value, ['hello', 'bye'])
        raises(PropertyTypeError, property_type1.check_value, 10)
        raises(PropertyTypeError, property_type1.check_value, RangeValue(10, 20))
        raises(PropertyTypeError, property_type1.check_value, [10, 20])

    def check_boolean_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.BOOLEAN)

        assert property_type1.is_atomic()
        assert not property_type1.is_int()
        assert not property_type1.is_string()
        assert not property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert not property_type1.is_list()
        assert not property_type1.is_table()
        assert property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.INT)
        assert property_type2 is not property_type1
        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.BOOLEAN)
        assert property_type2 is property_type1

        property_type1.check_value(True)
        property_type1.check_value(False)
        property_type1.check_value(0)
        property_type1.check_value(1)
        property_type1.check_value(None)
        raises(PropertyTypeError, property_type1.check_value, '')
        raises(PropertyTypeError, property_type1.check_value, [True])
        assert property_type1.format_value(True) == 'yes'
        assert property_type1.format_value(0) == 'no'

    def check_physical_value_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE)

        assert property_type1.is_atomic()
        assert not property_type1.is_int()
        assert not property_type1.is_string()
        assert property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert not property_type1.is_list()
        assert not property_type1.is_table()
        assert not property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE)
        assert property_type2 is property_type1

        inch = get_standard_unit('inch')
        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE,
            element_sub_type=inch)
        assert property_type2 is not property_type1

        property_type1.check_value(None)
        property_type1.check_value(PhysicalValue(10))
        property_type1.check_value(PhysicalValue(RangeValue(10, 20)))
        property_type2.check_value(PhysicalValue(10, 'inch'))
        property_type2.check_value(PhysicalValue(RangeValue(10, 20), 'inch'))
        property_type2.check_value(PhysicalValue(10, 'm'))
        property_type2.check_value(PhysicalValue(RangeValue(10, 20), 'm'))
        raises(PropertyTypeError, property_type1.check_value, 
            PhysicalValue(10, 'inch'))
        raises(PropertyTypeError, property_type2.check_value, PhysicalValue(10))
        raises(PropertyTypeError, property_type2.check_value, 
            PhysicalValue(10, 's'))
        raises(PropertyTypeError, property_type1.check_value, [PhysicalValue(10)])
        raises(PropertyTypeError, property_type2.check_value,
            [PhysicalValue(10, 'inch')])
        raises(PropertyTypeError,
            property_type1.check_value, 10)
        raises(PropertyTypeError,
            property_type1.check_value, RangeValue(10, 20))
        raises(PropertyTypeError,
            property_type1.check_value, [10, 20])
        raises(PropertyTypeError,
            property_type1.check_value, 'hello')
        raises(PropertyTypeError,
            property_type1.check_value, ['hello', 'bye'])
        raises(AssertionError,
            self.plib.get_property_type,
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE,
            element_sub_type=1)
        raises(AssertionError,
            self.plib.get_property_type,
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE, key_type=1)
        raises(AssertionError,
            self.plib.get_property_type,
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE, key_sub_type=1)

    def check_material_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)

        assert property_type1.is_atomic()
        assert not property_type1.is_int()
        assert not property_type1.is_string()
        assert not property_type1.is_physical_value()
        assert property_type1.is_material()
        assert not property_type1.is_list()
        assert not property_type1.is_table()
        assert not property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)
        assert property_type2 is property_type1

        silicone = self.mdb.get_material('silicone')
        gold = self.mdb.get_material('gold')
        inch = get_standard_unit('inch')

        property_type2 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)
        assert property_type2 is property_type1

        property_type1.check_value(None)
        property_type1.check_value(silicone)
        property_type1.check_value(gold)
        raises(PropertyTypeError,
            property_type1.check_value, [gold])
        raises(PropertyTypeError,
            property_type1.check_value, 'hello')
        raises(PropertyTypeError,
            property_type1.check_value, ['hello', 'bye'])
        property_type2.check_value(silicone)


    def check_list_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.LIST, PropertyType.INT)
        assert not property_type1.is_atomic()
        assert property_type1.is_int()
        assert not property_type1.is_string()
        assert not property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert property_type1.is_list()
        assert not property_type1.is_table()
        assert not property_type1.is_boolean()

        property_type2 = self.plib.get_property_type(
            PropertyType.LIST, PropertyType.INT)
        assert property_type2 is property_type1
        property_type2 = self.plib.get_property_type(
            PropertyType.LIST, PropertyType.STRING)
        assert property_type2 is not property_type1
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.STRING)
        assert property_type3 is property_type2.element_type

        assert not property_type2.is_int()
        assert property_type2.is_string()

        property_type1.check_value(None)
        property_type1.check_value([10])
        property_type1.check_value([10, 20])
        property_type1.check_value([RangeValue(10, 20)])
        property_type1.check_value([10, 20, RangeValue(10, 20)])
        raises(PropertyTypeError,
            property_type1.check_value, 10)
        raises(PropertyTypeError,
            property_type1.check_value, RangeValue(10, 20))
        raises(PropertyTypeError,
            property_type1.check_value, 'hello')

    def check_table_type (self):
        if get_property_db() is None:
            return
        property_type1 = self.plib.get_property_type(
            PropertyType.TABLE, PropertyType.PHYSICAL_VALUE,
            key_type=PropertyType.MATERIAL)

        assert not property_type1.is_atomic()
        assert not property_type1.is_int()
        assert not property_type1.is_string()
        assert property_type1.is_physical_value()
        assert not property_type1.is_material()
        assert not property_type1.is_list()
        assert property_type1.is_table()
        assert not property_type1.is_boolean()

        assert not property_type1.is_key_int()
        assert not property_type1.is_key_string()
        assert not property_type1.is_key_physical_value()
        assert property_type1.is_key_material()

        silicone = self.mdb.get_material('silicone')
        gold = self.mdb.get_material('gold')
        inch = get_standard_unit('inch')

        property_type2 = self.plib.get_property_type(
            PropertyType.TABLE, PropertyType.PHYSICAL_VALUE,
            key_type=PropertyType.MATERIAL)
        assert property_type2 is property_type1
        property_type2 = self.plib.get_property_type(
            PropertyType.TABLE, PropertyType.PHYSICAL_VALUE,
            key_type=PropertyType.MATERIAL)
        assert property_type2 is property_type1
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE)
        assert property_type3 is property_type1.element_type
        assert property_type3 is property_type2.element_type
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)
        assert property_type3 is property_type1.key_type
        assert property_type3 is property_type2.key_type
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)
        assert property_type3 is property_type1.key_type
        assert property_type3 is property_type2.key_type
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.PHYSICAL_VALUE)
        assert property_type3 is property_type1.element_type
        property_type3 = self.plib.get_property_type(
            PropertyType.ATOMIC, PropertyType.MATERIAL)
        assert property_type3 is property_type1.key_type

        property_type1.check_value(None)
        property_type1.check_value(
            {gold:PhysicalValue(10),
             silicone:PhysicalValue(RangeValue(10, 20))})

        raises(PropertyTypeError,
            property_type1.check_value, 10)
        raises(PropertyTypeError,
            property_type1.check_value, [10])
        raises(PropertyTypeError,
            property_type1.check_value, RangeValue(10, 20))
        raises(PropertyTypeError,
            property_type1.check_value, 'hello')
        raises(PropertyTypeError,
            property_type1.check_value, PhysicalValue(10))
        raises(PropertyTypeError,
            property_type1.check_value, [PhysicalValue(10)])
        raises(PropertyTypeError,
            property_type1.check_value, [gold])
        raises(AssertionError,
            self.plib.get_property_type,
            PropertyType.TABLE, PropertyType.INT)

if __name__ == "__main__":
    PropertyTypeTest()
