def run(self):
     '''
     Runs the widget
     
     :returns: True if there's no errors
     :rtype: Boolean
     '''
     
     project = PagLuxembourg.main.current_project
     
     if not project.isPagProject():
         return
     
     layer_structure_errors = list()
     data_errors = list()
     
     # 'MODIFICATION PAG' layer definition        
     layer_PAG = project.getModificationPagLayer()
             
     # 'MODIFICATION PAG' selection definition
     selection_PAG = layer_PAG.selectedFeatures()
     
     # Counting number entities in 'MODIFICATION PAG' selection
     entity_count_PAG = layer_PAG.selectedFeatureCount()
     
     # Iterates through XSD types
     for type in PagLuxembourg.main.xsd_schema.types:
         layer = project.getLayer(type)
         
         if layer is None:
             continue
         
         warn_errors, fatal_errors = self.checkLayerStructure(layer, type)
         layer_structure_errors = layer_structure_errors + warn_errors + fatal_errors
         
         if len(fatal_errors)>0:
             continue
         
         layer_data_errors = self.checkLayerData(selection_PAG, layer, type)
         data_errors.append(layer_data_errors)
     
     # Flatten data errors
     data_errors_flat = list()
     for layer, errors in data_errors:
         for feature, field, message in errors:
             data_errors_flat.append((layer, feature, field, message))
     
     valid = (len(layer_structure_errors) + len(data_errors_flat)) == 0
     
     # Messages display for number of selected entities
     if valid and entity_count_PAG == 1:
         PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
         PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker','Success'),
                                                                    QCoreApplication.translate('DataChecker','No errors found on entities that intersect {} selected entity in MODIFICATION PAG layer').format(entity_count_PAG))
     elif valid and entity_count_PAG == 0 :
         PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
         PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker_no','Success'),
                                                                    QCoreApplication.translate('DataChecker_no','No errors found'))
     elif valid and entity_count_PAG > 1 :
         PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
         PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker_many','Success'),
                                                                    QCoreApplication.translate('DataChecker_many','No errors found on entities that intersect {} selected entities in MODIFICATION PAG layer').format(entity_count_PAG))
     
     else:
         self.dlg = ErrorSummaryDialog(layer_structure_errors, data_errors)
         self.dlg.show()
     
     return valid 
    def run(self):
        '''
        Runs the widget
        
        :returns: True if there's no errors
        :rtype: Boolean
        '''

        project = PagLuxembourg.main.current_project

        if not project.isPagProject():
            return

        layer_structure_errors = list()
        data_errors = list()

        # 'MODIFICATION PAG' layer definition
        layer_PAG = project.getModificationPagLayer()

        # 'MODIFICATION PAG' selection definition
        selection_PAG = layer_PAG.selectedFeatures()

        # Counting number entities in 'MODIFICATION PAG' selection
        entity_count_PAG = layer_PAG.selectedFeatureCount()

        # Iterates through XSD types
        for type in PagLuxembourg.main.xsd_schema.types:
            layer = project.getLayer(type)

            if layer is None:
                continue

            warn_errors, fatal_errors = self.checkLayerStructure(layer, type)
            layer_structure_errors = layer_structure_errors + warn_errors + fatal_errors

            if len(fatal_errors) > 0:
                continue

            layer_data_errors = self.checkLayerData(selection_PAG, layer, type)
            data_errors.append(layer_data_errors)

        # Flatten data errors
        data_errors_flat = list()
        for layer, errors in data_errors:
            for feature, field, message in errors:
                data_errors_flat.append((layer, feature, field, message))

        valid = (len(layer_structure_errors) + len(data_errors_flat)) == 0

        # Messages display for number of selected entities
        if valid and entity_count_PAG == 1:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker', 'Success'),
                QCoreApplication.translate(
                    'DataChecker',
                    'No errors found on entities that intersect {} selected entity in MODIFICATION PAG layer'
                ).format(entity_count_PAG))
        elif valid and entity_count_PAG == 0:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker_no', 'Success'),
                QCoreApplication.translate('DataChecker_no',
                                           'No errors found'))
        elif valid and entity_count_PAG > 1:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker_many', 'Success'),
                QCoreApplication.translate(
                    'DataChecker_many',
                    'No errors found on entities that intersect {} selected entities in MODIFICATION PAG layer'
                ).format(entity_count_PAG))

        else:
            self.dlg = ErrorSummaryDialog(layer_structure_errors, data_errors)
            self.dlg.show()

        return valid
class DataChecker(object):
    '''
    Main class for the data checker widget
    '''

    def __init__(self):
        '''
        Constructor
        '''
    
    def run(self):
        '''
        Runs the widget
        
        :returns: True if there's no errors
        :rtype: Boolean
        '''
        
        project = PagLuxembourg.main.current_project
        
        if not project.isPagProject():
            return
        
        layer_structure_errors = list()
        data_errors = list()
        
        # 'MODIFICATION PAG' layer definition        
        layer_PAG = project.getModificationPagLayer()
                
        # 'MODIFICATION PAG' selection definition
        selection_PAG = layer_PAG.selectedFeatures()
        
        # Counting number entities in 'MODIFICATION PAG' selection
        entity_count_PAG = layer_PAG.selectedFeatureCount()
        
        # Iterates through XSD types
        for type in PagLuxembourg.main.xsd_schema.types:
            layer = project.getLayer(type)
            
            if layer is None:
                continue
            
            warn_errors, fatal_errors = self.checkLayerStructure(layer, type)
            layer_structure_errors = layer_structure_errors + warn_errors + fatal_errors
            
            if len(fatal_errors)>0:
                continue
            
            layer_data_errors = self.checkLayerData(selection_PAG, layer, type)
            data_errors.append(layer_data_errors)
        
        # Flatten data errors
        data_errors_flat = list()
        for layer, errors in data_errors:
            for feature, field, message in errors:
                data_errors_flat.append((layer, feature, field, message))
        
        valid = (len(layer_structure_errors) + len(data_errors_flat)) == 0
        
        # Messages display for number of selected entities
        if valid and entity_count_PAG == 1:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker','Success'),
                                                                       QCoreApplication.translate('DataChecker','No errors found on entities that intersect {} selected entity in MODIFICATION PAG layer').format(entity_count_PAG))
        elif valid and entity_count_PAG == 0 :
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker_no','Success'),
                                                                       QCoreApplication.translate('DataChecker_no','No errors found'))
        elif valid and entity_count_PAG > 1 :
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(QCoreApplication.translate('DataChecker_many','Success'),
                                                                       QCoreApplication.translate('DataChecker_many','No errors found on entities that intersect {} selected entities in MODIFICATION PAG layer').format(entity_count_PAG))
        
        else:
            self.dlg = ErrorSummaryDialog(layer_structure_errors, data_errors)
            self.dlg.show()
        
        return valid 
        
    # Datatype mapping allowed while checking. For a given XSD type, several QGIS type may be allowed or compatible
    XSD_QGIS_ALLOWED_DATATYPE_MAP = [(DataType.STRING, 'string'),
                                     (DataType.STRING, 'integer'),
                                     (DataType.STRING, 'double'),
                                     (DataType.INTEGER, 'integer'),
                                     (DataType.DOUBLE, 'double'),
                                     (DataType.DOUBLE, 'integer'),
                                     (DataType.DATE, 'date')]
    
    def checkLayerStructure(self, layer, xsd_type):
        '''
        Checks a layer structure against the XSD type
        Missing field, data type mismatch
        
        :param layer: The vector layer to check
        :type layer: QgsVectorLayer
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of warning and fatal error
        :rtype: Tuple : warning, fatal. Layer (QgsVectorLayer), field (PAGField), message (str, QString)
        '''
        
        native_fields = PagLuxembourg.main.current_project.getNativeFields(xsd_type)
        warn_errors = list()
        fatal_errors = list()
        
        # Check geometry type
        if xsd_type.geometry_type is not None and XSD_QGIS_GEOMETRYTYPE_MAP[xsd_type.geometry_type] != layer.geometryType():
            fatal_errors.append((layer, None, QCoreApplication.translate('DataChecker','Geometry type mismatch, expected : {}').format(xsd_type.geometry_type)))
        
        # Check field structure
        for field in xsd_type.fields:
            # Check field missing
            if self._getNativeField(native_fields, field.name) == None:
                if field.nullable:
                    warn_errors.append((layer, field, QCoreApplication.translate('DataChecker','Nullable field is missing')))
                else:
                    warn_errors.append((layer, field, QCoreApplication.translate('DataChecker','Non nullable field is missing')))
                
                continue
            
            # Check field datatype
            layer_field_name, layer_field_type = self._getNativeField(native_fields, field.name)
            found = False
            for xsd_type, qgis_type in self.XSD_QGIS_ALLOWED_DATATYPE_MAP:
                if layer_field_type == qgis_type and field.type == xsd_type:
                    found = True
                    break
            
            if not found:
                fatal_errors.append((layer, field, QCoreApplication.translate('DataChecker','Field datatype mismatch, expected : {}').format(field.type)))
        
        return warn_errors, fatal_errors
    
    def _getNativeField(self, fields, name):
        '''
        Get a native field  from name
        '''
        for field in fields:
            if field[0]==name:
                return field
        
        return None
    
    def checkLayerData(self, selection_PAG, layer, xsd_type):
        '''
        Checks the data of a layer against the XSD type
        
        :param selection_PAG: Selected features from the Modification PAG layer
        :type selection_PAG: QgsFeatureList
        
        :param layer: The vector layer to check
        :type layer: QgsVectorLayer
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of data error
        :rtype: Tuples : Layer (QgsVectorLayer), list of tuple Feature (QgsFeature), field (PAGField), message (str, QString)
        '''
        
        errors = list()
        areas = []
        
        # Check if a selection exists in 'MODIFICATION PAG'
        if len(selection_PAG) > 0 :
            
            # Selection by intersection with 'MODIFICATION PAG' layer
            for PAG_feature in selection_PAG:
                cands = layer.getFeatures()
                for layer_features in cands:
                    if PAG_feature.geometry().intersects(layer_features.geometry()):
                        areas.append(layer_features.id())

            layer.select(areas)
            selection_entities_from_PAG = layer.selectedFeatures()

            for feature in selection_entities_from_PAG :
                errors += self.checkFeatureData(feature, xsd_type)
                    
        else:
            
            for feature in layer.dataProvider().getFeatures() :
                errors += self.checkFeatureData(feature, xsd_type)
        
        return layer, errors
    
    def checkFeatureData(self, feature, xsd_type):
        '''
        Checks the data of a feature against the XSD type
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''
        
        errors = list()
        
        # Check geometry
        if xsd_type.geometry_type is not None:
            errors += self.checkFeatureGeometry(feature)
        
        for field in feature.fields():
            xsd_field = xsd_type.getField(field.name())
            
            # Check if field exists in XSD
            if xsd_field is None:
                continue
            
            errors += self.checkFeatureFieldData(feature, xsd_field)
        
        return errors
    
    def checkFeatureFieldData(self, feature, xsd_field):
        '''
        Checks the data of a feature against the XSD type
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :param xsd_field: XSD type field
        :type xsd_field: PAGField
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''
        
        errors = list()
        
        field_value = feature.attribute(xsd_field.name)
        
        # Check null value
        if field_value is None or field_value == NULL:
            if not xsd_field.nullable:
                errors.append((feature, xsd_field, QCoreApplication.translate('DataChecker','Null value in non nullable field')))
            
            return errors
        
        # Check numeric values
        if xsd_field.type in [DataType.INTEGER,DataType.DOUBLE]:
            numeric_value = float(field_value)
            
            # Check min value
            if xsd_field.minvalue is not None:
                min_value = float(xsd_field.minvalue)
                if numeric_value < min_value:
                    errors.append((feature, xsd_field, QCoreApplication.translate('DataChecker','Value ({}) less than minimum value ({})').format(numeric_value, min_value)))
            
            # Check max value
            if xsd_field.maxvalue is not None:
                max_value = float(xsd_field.maxvalue)
                if numeric_value > max_value:
                    errors.append((feature, xsd_field, QCoreApplication.translate('DataChecker','Value ({}) greater than maximum value ({})').format(numeric_value, max_value)))
            
        # Check string values
        if xsd_field.type == DataType.STRING:
            text_value = unicode(field_value)
            
            # Check value length
            if xsd_field.length is not None:
                text_length = len(text_value)
                max_length = int(xsd_field.length)
                if text_length > max_length:
                    errors.append((feature, xsd_field, QCoreApplication.translate('DataChecker','Text length ({}) greater than field length ({})').format(text_length, max_length)))
            
            # Check enumeration
            if xsd_field.listofvalues is not None:
                if text_value not in xsd_field.listofvalues:
                    errors.append((feature, xsd_field, QCoreApplication.translate('DataChecker','Text ({}) not in field list of values').format(text_value)))
        
        return errors
    
    def checkFeatureGeometry(self, feature):
        '''
        Checks the geometry of a feature
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''
        
        errors = list()
        
        if feature.geometry() is None or feature.geometry().isEmpty():
            errors.append((feature, None, QCoreApplication.translate('DataChecker','Geometry is empty')))
        else:
            errors2 = feature.geometry().validateGeometry()
                        
            for error in errors2:
                errors.append((feature, None, error.what()))
        
        return errors
class DataChecker(object):
    '''
    Main class for the data checker widget
    '''
    def __init__(self):
        '''
        Constructor
        '''

    def run(self):
        '''
        Runs the widget
        
        :returns: True if there's no errors
        :rtype: Boolean
        '''

        project = PagLuxembourg.main.current_project

        if not project.isPagProject():
            return

        layer_structure_errors = list()
        data_errors = list()

        # 'MODIFICATION PAG' layer definition
        layer_PAG = project.getModificationPagLayer()

        # 'MODIFICATION PAG' selection definition
        selection_PAG = layer_PAG.selectedFeatures()

        # Counting number entities in 'MODIFICATION PAG' selection
        entity_count_PAG = layer_PAG.selectedFeatureCount()

        # Iterates through XSD types
        for type in PagLuxembourg.main.xsd_schema.types:
            layer = project.getLayer(type)

            if layer is None:
                continue

            warn_errors, fatal_errors = self.checkLayerStructure(layer, type)
            layer_structure_errors = layer_structure_errors + warn_errors + fatal_errors

            if len(fatal_errors) > 0:
                continue

            layer_data_errors = self.checkLayerData(selection_PAG, layer, type)
            data_errors.append(layer_data_errors)

        # Flatten data errors
        data_errors_flat = list()
        for layer, errors in data_errors:
            for feature, field, message in errors:
                data_errors_flat.append((layer, feature, field, message))

        valid = (len(layer_structure_errors) + len(data_errors_flat)) == 0

        # Messages display for number of selected entities
        if valid and entity_count_PAG == 1:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker', 'Success'),
                QCoreApplication.translate(
                    'DataChecker',
                    'No errors found on entities that intersect {} selected entity in MODIFICATION PAG layer'
                ).format(entity_count_PAG))
        elif valid and entity_count_PAG == 0:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker_no', 'Success'),
                QCoreApplication.translate('DataChecker_no',
                                           'No errors found'))
        elif valid and entity_count_PAG > 1:
            PagLuxembourg.main.qgis_interface.messageBar().clearWidgets()
            PagLuxembourg.main.qgis_interface.messageBar().pushSuccess(
                QCoreApplication.translate('DataChecker_many', 'Success'),
                QCoreApplication.translate(
                    'DataChecker_many',
                    'No errors found on entities that intersect {} selected entities in MODIFICATION PAG layer'
                ).format(entity_count_PAG))

        else:
            self.dlg = ErrorSummaryDialog(layer_structure_errors, data_errors)
            self.dlg.show()

        return valid

    # Datatype mapping allowed while checking. For a given XSD type, several QGIS type may be allowed or compatible
    XSD_QGIS_ALLOWED_DATATYPE_MAP = [(DataType.STRING, 'string'),
                                     (DataType.STRING, 'integer'),
                                     (DataType.STRING, 'double'),
                                     (DataType.INTEGER, 'integer'),
                                     (DataType.DOUBLE, 'double'),
                                     (DataType.DOUBLE, 'integer'),
                                     (DataType.DATE, 'date')]

    def checkLayerStructure(self, layer, xsd_type):
        '''
        Checks a layer structure against the XSD type
        Missing field, data type mismatch
        
        :param layer: The vector layer to check
        :type layer: QgsVectorLayer
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of warning and fatal error
        :rtype: Tuple : warning, fatal. Layer (QgsVectorLayer), field (PAGField), message (str, QString)
        '''

        native_fields = PagLuxembourg.main.current_project.getNativeFields(
            xsd_type)
        warn_errors = list()
        fatal_errors = list()

        # Check geometry type
        if xsd_type.geometry_type is not None and XSD_QGIS_GEOMETRYTYPE_MAP[
                xsd_type.geometry_type] != layer.geometryType():
            fatal_errors.append(
                (layer, None,
                 QCoreApplication.translate(
                     'DataChecker',
                     'Geometry type mismatch, expected : {}').format(
                         xsd_type.geometry_type)))

        # Check field structure
        for field in xsd_type.fields:
            # Check field missing
            if self._getNativeField(native_fields, field.name) == None:
                if field.nullable:
                    warn_errors.append((layer, field,
                                        QCoreApplication.translate(
                                            'DataChecker',
                                            'Nullable field is missing')))
                else:
                    warn_errors.append((layer, field,
                                        QCoreApplication.translate(
                                            'DataChecker',
                                            'Non nullable field is missing')))

                continue

            # Check field datatype
            layer_field_name, layer_field_type = self._getNativeField(
                native_fields, field.name)
            found = False
            for xsd_type, qgis_type in self.XSD_QGIS_ALLOWED_DATATYPE_MAP:
                if layer_field_type == qgis_type and field.type == xsd_type:
                    found = True
                    break

            if not found:
                fatal_errors.append(
                    (layer, field,
                     QCoreApplication.translate(
                         'DataChecker',
                         'Field datatype mismatch, expected : {}').format(
                             field.type)))

        return warn_errors, fatal_errors

    def _getNativeField(self, fields, name):
        '''
        Get a native field  from name
        '''
        for field in fields:
            if field[0] == name:
                return field

        return None

    def checkLayerData(self, selection_PAG, layer, xsd_type):
        '''
        Checks the data of a layer against the XSD type
        
        :param selection_PAG: Selected features from the Modification PAG layer
        :type selection_PAG: QgsFeatureList
        
        :param layer: The vector layer to check
        :type layer: QgsVectorLayer
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of data error
        :rtype: Tuples : Layer (QgsVectorLayer), list of tuple Feature (QgsFeature), field (PAGField), message (str, QString)
        '''

        errors = list()
        areas = []

        # Check if a selection exists in 'MODIFICATION PAG'
        if len(selection_PAG) > 0:

            # Selection by intersection with 'MODIFICATION PAG' layer
            for PAG_feature in selection_PAG:
                cands = layer.getFeatures()
                for layer_features in cands:
                    if PAG_feature.geometry().intersects(
                            layer_features.geometry()):
                        areas.append(layer_features.id())

            if layer.geometryType() == QGis.NoGeometry:
                layer.selectAll()
            else:
                layer.select(areas)
            selection_entities_from_PAG = layer.selectedFeatures()

            for feature in selection_entities_from_PAG:
                errors += self.checkFeatureData(feature, xsd_type)

        else:

            for feature in layer.dataProvider().getFeatures():
                errors += self.checkFeatureData(feature, xsd_type)

        return layer, errors

    def checkFeatureData(self, feature, xsd_type):
        '''
        Checks the data of a feature against the XSD type
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :param type: XSD schema type
        :type type: PAGType
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''

        errors = list()

        # Check geometry
        if xsd_type.geometry_type is not None:
            errors += self.checkFeatureGeometry(feature)

        for field in feature.fields():
            xsd_field = xsd_type.getField(field.name())

            # Check if field exists in XSD
            if xsd_field is None:
                continue

            errors += self.checkFeatureFieldData(feature, xsd_field)

        return errors

    def checkFeatureFieldData(self, feature, xsd_field):
        '''
        Checks the data of a feature against the XSD type
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :param xsd_field: XSD type field
        :type xsd_field: PAGField
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''

        errors = list()

        field_value = feature.attribute(xsd_field.name)

        # Check null value
        if field_value is None or field_value == NULL:
            if not xsd_field.nullable:
                errors.append((feature, xsd_field,
                               QCoreApplication.translate(
                                   'DataChecker',
                                   'Null value in non nullable field')))

            return errors

        # Check numeric values
        if xsd_field.type in [DataType.INTEGER, DataType.DOUBLE]:
            numeric_value = float(field_value)

            # Check min value
            if xsd_field.minvalue is not None:
                min_value = float(xsd_field.minvalue)
                if numeric_value < min_value:
                    errors.append(
                        (feature, xsd_field,
                         QCoreApplication.translate(
                             'DataChecker',
                             'Value ({}) less than minimum value ({})').format(
                                 numeric_value, min_value)))

            # Check max value
            if xsd_field.maxvalue is not None:
                max_value = float(xsd_field.maxvalue)
                if numeric_value > max_value:
                    errors.append(
                        (feature, xsd_field,
                         QCoreApplication.translate(
                             'DataChecker',
                             'Value ({}) greater than maximum value ({})').
                         format(numeric_value, max_value)))

        # Check string values
        if xsd_field.type == DataType.STRING:
            text_value = unicode(field_value)

            # Check value length
            if xsd_field.length is not None:
                text_length = len(text_value)
                max_length = int(xsd_field.length)
                if text_length > max_length:
                    errors.append(
                        (feature, xsd_field,
                         QCoreApplication.translate(
                             'DataChecker',
                             'Text length ({}) greater than field length ({})'
                         ).format(text_length, max_length)))

            # Check enumeration
            if xsd_field.listofvalues is not None:
                if text_value not in xsd_field.listofvalues:
                    errors.append(
                        (feature, xsd_field,
                         QCoreApplication.translate(
                             'DataChecker',
                             'Text ({}) not in field list of values').format(
                                 text_value)))

        return errors

    def checkFeatureGeometry(self, feature):
        '''
        Checks the geometry of a feature
        
        :param feature: The feature to check
        :type feature: QgsFeature
        
        :returns: A list of  error
        :rtype: List of tuples : Feature (QgsFeature), field (PAGField), message (str, QString)
        '''

        errors = list()

        if feature.geometry() is None or feature.geometry().isEmpty():
            errors.append((feature, None,
                           QCoreApplication.translate('DataChecker',
                                                      'Geometry is empty')))
        else:
            errors2 = feature.geometry().validateGeometry()

            for error in errors2:
                errors.append((feature, None, error.what()))

        return errors