Exemplo n.º 1
0
    def set_fixed_error(self, error_t_id, fixed):
        # Save to the intermediate dict of data and to the underlying data source whether an error is fixed or not
        db = self.__qr_engine.get_db_quality()
        idx_state = self.__get_error_layer().fields().indexOf(
            db.names.ERR_QUALITY_ERROR_T_ERROR_STATE_F)

        value = LADMNames.ERR_ERROR_STATE_D_FIXED_V if fixed else LADMNames.ERR_ERROR_STATE_D_ERROR_V
        fixed_or_error_t_id = self.__get_error_state_t_id(value)

        if fixed_or_error_t_id is None:
            self.logger.critical(
                __name__,
                "The error state t_id couldn't be found for value '{}'!".
                format(value))
            return

        # Save to dict
        self.get_error_results_data()[error_t_id].setAttribute(
            idx_state, fixed_or_error_t_id)

        fids = LADMData.get_fids_from_key_values(self.__get_error_layer(),
                                                 db.names.T_ID_F, [error_t_id])

        # Save to underlying data source
        if fids:
            res = self.__get_error_layer().dataProvider(
            ).changeAttributeValues(
                {fids[0]: {
                     idx_state: fixed_or_error_t_id
                 }})

            if not res:
                self.logger.critical(__name__,
                                     "Error modifying the error state value!")
        else:
            self.logger.critical(
                __name__, "Error with t_id '' not found!".format(error_t_id))
    def save_errors(db_qr,
                    rule_code,
                    error_code,
                    error_data,
                    target_layer,
                    ili_name=None):
        """
        Save error data in the quality error model by error_code, which means that you should call this function once
        per error type. Accepts both, spatial and non-spatial errors.

        :param db_qr: DB Connector
        :param rule_code: Rule code as specified in the external catalogs.
        :param error_code: Error code as specified in the external catalogs.
        :param error_data: Dict of lists:
                               {'geometries': [geometries], 'data': [obj_uuids, rel_obj_uuids, values, details, state]}
                               Note: this dict will always have 2 elements.
                               Note 2: For geometry errors, this dict will always have the same number of elements in
                                       each of the two lists (and the element order matters!).
                               Note 3: For geometryless errors, the 'geometries' value won't be even read.
        :param target_layer: Value of EnumQualityRuleType.
        :param ili_name: Interlis name of the class where the object uuids can be found.
        :return: Tuple (res: boolean, msg: string)
        """
        if not hasattr(db_qr.names, "T_ID_F"):
            db_qr.test_connection()

        names = db_qr.names
        layers = {
            names.ERR_QUALITY_ERROR_T: None,
            names.ERR_RULE_TYPE_T: None,
            names.ERR_ERROR_TYPE_T: None
        }

        if target_layer == EnumQualityRuleType.POINT:
            layers[names.ERR_POINT_T] = None
        elif target_layer == EnumQualityRuleType.LINE:
            layers[names.ERR_LINE_T] = None
        elif target_layer == EnumQualityRuleType.POLYGON:
            layers[names.ERR_POLYGON_T] = None

        app.core.get_layers(db_qr, layers, load=True)

        if not layers:
            return False, "At least one layer was not found in the quality error db!"

        # We do now a soon check of rule code and error code to stop if cannot be found
        fids = LADMData.get_fids_from_key_values(layers[names.ERR_RULE_TYPE_T],
                                                 names.ERR_RULE_TYPE_T_CODE_F,
                                                 [rule_code])
        if not fids:
            return False, "There was a problem saving quality error data. The rule '{}' cannot be found in the database. Is that rule in any registered catalog?".format(
                rule_code)
        rule_code_id = fids[0]

        fids = LADMData.get_fids_from_key_values(
            layers[names.ERR_ERROR_TYPE_T], names.ERR_ERROR_TYPE_T_CODE_F,
            [error_code])
        if not fids:
            return False, "There was a problem saving quality error data. The error '{}' cannot be found in the database. Is that error in any registered catalog?".format(
                error_code)
        error_code_id = fids[0]

        qr_error_layer = layers[names.ERR_QUALITY_ERROR_T]

        # First we deal with geometries
        geom_layer = None
        idx_geometry_fk = None
        geom_t_ids = list()  # To store fks (geom t_id)
        if target_layer == EnumQualityRuleType.POINT:
            geom_layer = layers[names.ERR_POINT_T]
            idx_geometry_fk = qr_error_layer.fields().indexOf(
                names.ERR_QUALITY_ERROR_T_POINT_F)
        elif target_layer == EnumQualityRuleType.LINE:
            geom_layer = layers[names.ERR_LINE_T]
            idx_geometry_fk = qr_error_layer.fields().indexOf(
                names.ERR_QUALITY_ERROR_T_LINE_F)
        elif target_layer == EnumQualityRuleType.POLYGON:
            geom_layer = layers[names.ERR_POLYGON_T]
            idx_geometry_fk = qr_error_layer.fields().indexOf(
                names.ERR_QUALITY_ERROR_T_POLYGON_F)

        if geom_layer:
            idx_t_ili_tid_geom = geom_layer.fields().indexOf(names.T_ILI_TID_F)
            geometries = error_data['geometries']

            features = list()
            for geometry in geometries:
                new_feature = QgsVectorLayerUtils().createFeature(
                    geom_layer, geometry,
                    {idx_t_ili_tid_geom: str(uuid.uuid4())})
                features.append(new_feature)

            res_geom, out_features = geom_layer.dataProvider().addFeatures(
                features)
            if res_geom:
                geom_t_ids = [
                    out_feature[names.T_ID_F] for out_feature in out_features
                ]
            else:
                return False, "There was a problem saving error geometries for error code '{}'!".format(
                    error_code)

        # Now we deal with the alphanumeric data
        idx_t_ili_tid = qr_error_layer.fields().indexOf(names.T_ILI_TID_F)
        idx_rule_type = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_RULE_TYPE_F)
        idx_error_type = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_ERROR_TYPE_F)
        idx_object_ids = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_OBJECT_IDS_F)
        idx_rel_object_ids = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_RELATED_OBJECT_IDS_F)
        idx_values = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_VALUES_F)
        idx_ili_name = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_ILI_NAME_F)
        idx_details = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_DETAILS_F)
        idx_error_state = qr_error_layer.fields().indexOf(
            names.ERR_QUALITY_ERROR_T_ERROR_STATE_F)

        features = list()
        for i, data in enumerate(error_data['data']):
            attr_map = {
                idx_t_ili_tid: str(uuid.uuid4()),
                idx_rule_type: rule_code_id,
                idx_error_type: error_code_id,
                idx_object_ids: data[0],
                idx_rel_object_ids: data[1],
                idx_values: data[2],
                idx_details: data[3],
                idx_ili_name: ili_name,
                idx_error_state: data[4]
            }
            if geom_layer:
                attr_map[idx_geometry_fk] = geom_t_ids[
                    i]  # We take advantage of the preserved order here

            features.append(QgsVectorLayerUtils().createFeature(
                qr_error_layer, attributes=attr_map))

        res_data, out_features = qr_error_layer.dataProvider().addFeatures(
            features)
        if not res_data:
            return False, "There was a problem saving error alphanumeric data for error code '{}'! Details from the provider: {}".format(
                error_code,
                qr_error_layer.dataProvider().lastError())

        return True, "Success!"