def init_before_test(self):
     plugins_info = self.create_plugins().get_information()
     plugins_catalog = CUtils.dict_value_by_name(
         plugins_info, CPlugins.Plugins_Info_Catalog_Title, '')
     self._test_file_root_path = settings.application.xpath_one(
         self.Path_Setting_Dir_Test_Data, '')
     self._test_file_parent_path = CFile.join_file(
         settings.application.xpath_one(self.Path_Setting_Dir_Test_Data,
                                        ''), plugins_catalog)
예제 #2
0
 def metadata_bus_dict_process_custom(self, metadata_bus_dict):
     """
     对部分需要进行运算的数据进行处理
     """
     super().metadata_bus_dict_process_custom(metadata_bus_dict)
     productattribute = CUtils.dict_value_by_name(metadata_bus_dict,
                                                  'productattribute', None)
     if not CUtils.equal_ignore_case(productattribute, ''):
         if len(productattribute) > 2:
             metadata_bus_dict['productattribute'] = productattribute[:2]
예제 #3
0
    def run(self):
        if not CUtils.equal_ignore_case(CSys.get_platform_system_name(),
                                        self.OS_Windows):
            base_signal.signal(base_signal.SIGCHLD, self.wait_child)

        CLogger().info('控制中心进程[{0}]启动运行...'.format(self.pid))
        # 此时, 才在controlCenter的进程中
        host_settings_dict = CUtils.dict_value_by_name(
            self.__shared_control_center_info__, self.NAME_CMD_SETTINGS, None)
        settings.application.load_obj(host_settings_dict)
        settings.application.init_sys_path()

        CLogger().info('控制中心进程[{0}]启动哨兵值守进程...'.format(self.pid))
        self.__control_center_manager__ = Manager()
        self.__control_center_params = self.__control_center_manager__.dict()
        self.__control_center_objects__ = self.__control_center_manager__.dict(
        )
        self.__control_center_objects_locker__ = self.__control_center_manager__.Lock(
        )

        self.__sentinel_manager__ = Manager()
        self.__sentinel_queue__ = self.__sentinel_manager__.Queue()
        self.__sentinel_stop_event__ = self.__sentinel_manager__.Event()

        self.__control_center_params[
            self.NAME_CMD_SETTINGS] = host_settings_dict

        self.__sentinel_process__ = CSentinel(
            self.__control_center_objects_locker__,
            self.__control_center_objects__, self.__sentinel_stop_event__,
            self.__sentinel_queue__, self.__control_center_params)
        self.__sentinel_process__.daemon = True
        self.__sentinel_process__.start()

        while True:
            CLogger().info('控制中心进程[{0}]开始检查接收任务队列...'.format(self.pid))

            if self.process_queue_command(
            ) == self.const_command_queue_process_result_notify_terminal:
                break

            CLogger().info('控制中心进程[{0}]开始检查哨兵反馈的消息...'.format(self.pid))
            self.process_queue_sentinel()

            CLogger().info('控制中心进程[{0}]开始同步控制中心对外公布的数据...'.format(self.pid))
            # 同步一下控制中心的对外公布数据
            self.sync_shared_control_center_info()
            # 休息一下
            time.sleep(3)

        CLogger().info('控制中心进程[{0}]开始进行退出前的准备工作, 该过程会比较复杂漫长...'.format(
            self.pid))
        # 开始处理退出工作
        self.before_stop()
예제 #4
0
    def batch_qa_metadata_bus_json_item(self, list_qa: list):
        """
        批量处理json格式的业务元数据中的质检项目
        :param list_qa:
        :return:
        """
        if len(list_qa) == 0:
            return

        for qa_item in list_qa:
            list_result = CAudit.a_json_element(
                CUtils.dict_value_by_name(qa_item, self.Name_ID, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Title, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Group, self.QA_Group_Data_Integrity),
                CUtils.dict_value_by_name(qa_item, self.Name_Result, self.QA_Result_Pass),
                self.metadata.metadata_bus_json(),
                CUtils.dict_value_by_name(qa_item, self.Name_XPath, ''),
                qa_item
            )
            item_result = self.get_qa_result_from_list(list_result)
            self.metadata.quality.append_metadata_bus_quality(item_result)
예제 #5
0
    def run(self):
        # 此时, 才在worker的进程中
        host_settings_dict = CUtils.dict_value_by_name(self.__params__, self.NAME_CMD_SETTINGS, None)
        settings.application.load_obj(host_settings_dict)
        settings.application.init_sys_path()

        # 在终止进程时,部分进程将得到信号,进入运行机制,但此之前,停止信号应该已经设置!!!进程将直接结束
        if not self.accept_stop_message():
            self.__runner__ = self.get_or_create_worker_execute(self.__cmd_id__, self.__cmd_trigger__,
                                                                self.__cmd_algorithm__, self.__cmd_params__,
                                                                self.__stop_event__)
            if self.__runner__ is not None:
                self.__runner__.start()
예제 #6
0
    def __plugins_classified_of_directory__(
            cls, file_info: CDMFilePathInfoEx) -> CPlugins:
        """
        使用系统目录下的所有插件进行识别
        :param file_info:
        :return:
        """
        target = file_info.file_main_name
        target_type = file_info.file_type
        plugins_root_package_name = '{0}.{1}'.format(
            CSys.get_plugins_package_root_name(), target_type)
        path = CFile.join_file(CSys.get_plugins_root_dir(), target_type)
        plugins_file_list = CFile.file_or_subpath_of_path(
            path, '{0}_*.{1}'.format(cls.Name_Plugins, cls.FileExt_Py))
        for file_name_without_path in plugins_file_list:
            file_main_name = CFile.file_main_name(file_name_without_path)
            try:
                class_classified_obj = CObject.create_plugins_instance(
                    plugins_root_package_name, file_main_name, file_info)
                obj_info = class_classified_obj.get_information()
                # 王西亚 添加逻辑于2021-02-12, 解决项目插件调试不方便的问题
                obj_classified_valid = False
                obj_owner_project_id = CUtils.dict_value_by_name(
                    obj_info, CPlugins.Plugins_Info_Project_ID, None)
                system_project_id = settings.application.xpath_one(
                    cls.Path_Setting_Project_ID, None)
                if obj_owner_project_id is None:
                    obj_classified_valid = True
                else:
                    obj_classified_valid = CUtils.equal_ignore_case(
                        obj_owner_project_id, system_project_id)

                if obj_classified_valid:
                    object_confirm, object_name = class_classified_obj.classified(
                    )
                    if object_confirm != cls.Object_Confirm_IUnKnown:
                        obj_id = class_classified_obj.get_id()
                        CLogger().debug('{0} is classified as {1}.{2}'.format(
                            target, obj_info, obj_id))
                        return class_classified_obj
            except Exception as error:
                CLogger().debug('插件[{0}]解析出现异常, 错误信息为: [{1}], 请检查!'.format(
                    file_main_name, error.__str__()))
                if settings.application.xpath_one(
                        '{0}.{1}'.format(cls.Name_Application, cls.Name_Debug),
                        cls.DB_False) == cls.DB_True:
                    raise
                else:
                    continue
        else:
            return None
예제 #7
0
    def __find_column_data_set_method(self, column_obj: CColumn, data_source: CDataSetSeqReader):
        pipe_list = CUtils.dict_value_by_name(self.__config, self.Name_Pipe, None)
        option = CUtils.dict_value_by_name(self.__config, self.Name_Option, None)
        same_field_name_match = CUtils.dict_value_by_name(option, 'same_field_name_match', True)
        if pipe_list is not None:
            for pipe in pipe_list:
                if CUtils.equal_ignore_case(
                        CUtils.dict_value_by_name(pipe, self.Name_Field, None),
                        column_obj.name
                ):
                    return pipe

        if same_field_name_match:
            for field_index in range(data_source.field_count()):
                field_name = data_source.field_name(field_index)
                if CUtils.equal_ignore_case(field_name, column_obj.name):
                    return {
                        self.Name_Field: column_obj.name,
                        self.Name_Type: self.Name_Common,
                        self.Name_Value: '${0}'.format(field_name)
                    }
        else:
            return None
예제 #8
0
    def run(self):
        # 此时, 才在sentinel的进程中
        host_settings_dict = CUtils.dict_value_by_name(
            self.__control_center_params, self.NAME_CMD_SETTINGS, None)
        settings.application.load_obj(host_settings_dict)
        settings.application.init_sys_path()

        while True:
            # 在终止进程时,部分进程将得到信号,进入运行机制,但此之前,停止信号应该已经设置!!!进程将直接结束
            if self.__stop_event__.is_set():
                return

            self.check_process_alive()
            time.sleep(10)
예제 #9
0
    def batch_qa_file(self, list_qa: list):
        """
        批量处理数据完整性方面的质检项目
        :param list_qa:
        :return:
        """
        if len(list_qa) == 0:
            return

        for qa_item in list_qa:
            list_result = CAudit.a_file(
                CUtils.dict_value_by_name(qa_item, self.Name_ID, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Title, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Group, self.QA_Group_Data_Integrity),
                CUtils.dict_value_by_name(qa_item, self.Name_Result, self.QA_Result_Pass),
                CFile.join_file(
                    self.file_content.content_root_dir,
                    CUtils.dict_value_by_name(qa_item, self.Name_FileName, '')
                ),
                qa_item
            )
            item_result = self.get_qa_result_from_list(list_result)
            self.metadata.quality.append_total_quality(item_result)
예제 #10
0
 def begin_compress(self):
     """
     开始压缩
     -p后面接的是压缩到那个地方的路径,默认是压缩到当前工作的目录
     -m后面接的是一个数字0或者1表示压缩方式,默认是0   1 =  zipfile.ZIP_STORED , 0 = zipfile.ZIP_DEFLATED
     :return:
     """
     parser = argparse.ArgumentParser(
         description='add zip path, eg:"/user/bin/src/"')
     parser.add_argument("-p",
                         help='path no name, eg:"/user/bin/src/"',
                         default=CFile.file_abs_path('.') +
                         CFile.unify_seperator + "zip" +
                         CFile.unify_seperator)
     parser.add_argument(
         "-m",
         help=
         'zip methods, use int, eg: 1 =  zipfile.ZIP_STORED and 0 = zipfile.ZIP_DEFLATED',
         type=int,
         default=0)
     args = parser.parse_args()
     path = args.p
     zip_way = args.m
     plugin_path = self.search_type()
     print("开始创建目录.........")
     print("创建目录成功")
     for plugin_name in plugin_path:
         path_with_name = path + CUtils.dict_value_by_name(
             plugin_name, 'type',
             '') + CFile.unify_seperator + CUtils.dict_value_by_name(
                 plugin_name, 'target', '')
         print("压缩路径是%s" % path_with_name)
         test = CZip_ZipFile(path_with_name)
         test.new(zip_way)
         test.add_file_or_path(plugin_name)
         test.close()
     print("所有插件压缩完成")
 def metadata_bus_dict_process_custom(self, metadata_bus_dict):
     """
     对部分需要进行运算的数据进行处理
     """
     super().metadata_bus_dict_process_custom(metadata_bus_dict)
     resolution = CUtils.dict_value_by_name(metadata_bus_dict, 'resolution',
                                            None)
     if not CUtils.equal_ignore_case(resolution, ''):
         resolution_list = re.split(r'[/]|\s+', resolution.strip())
         if len(resolution_list) > 0:
             temp_resolution_list = []
             for temp_resolution in resolution_list:
                 temp_resolution_list.append(
                     CUtils.to_decimal(temp_resolution))
             metadata_bus_dict['resolution'] = min(temp_resolution_list)
예제 #12
0
    def __append_quality_info(self, xml_node, audit_result: dict):
        quality_id = CUtils.dict_value_by_name(audit_result, self.Name_ID, '')
        quality_title = CUtils.dict_value_by_name(audit_result,
                                                  self.Name_Title, '')
        quality_group = CUtils.dict_value_by_name(audit_result,
                                                  self.Name_Group,
                                                  self.QA_Group_Data_Integrity)
        quality_result = CUtils.dict_value_by_name(audit_result,
                                                   self.Name_Result,
                                                   self.QA_Result_Pass)
        quality_memo = CUtils.dict_value_by_name(audit_result,
                                                 self.Name_Message, '')

        temp_node = CXml.node_xpath_one(
            xml_node, './{0}[@id="{1}"]'.format(self.Name_Item, quality_id))
        if temp_node is not None:
            CXml.remove(temp_node)

        temp_node = CXml.create_element(xml_node, self.Name_Item)
        CXml.set_attr(temp_node, self.Name_ID, quality_id)
        CXml.set_attr(temp_node, self.Name_Group, quality_group)
        CXml.set_attr(temp_node, self.Name_Title, quality_title)
        CXml.set_attr(temp_node, self.Name_Result, quality_result)
        CXml.set_element_text(temp_node, quality_memo)
예제 #13
0
    def process_mission(self, dataset) -> str:
        """
        :param dataset:
        :return:
        """
        ds_na_id = dataset.value_by_name(0, 'na_id', '')
        ds_app_id = dataset.value_by_name(0, 'app_id', '')
        ds_object_id = dataset.value_by_name(0, 'object_id', '')
        ds_object_type = dataset.value_by_name(0, 'object_type', '')
        ds_object_name = dataset.value_by_name(0, 'object_name', '')
        ds_object_access = dataset.value_by_name(0, 'object_access',
                                                 self.DataAccess_Forbid)

        CLogger().debug('与第三方模块[{0}]同步的对象为: [{1}]'.format(
            ds_app_id, ds_object_name))
        try:
            module_file_name = CFile.join_file(
                CSys.get_metadata_data_access_modules_root_dir(),
                '{0}.{1}'.format(ds_app_id, self.FileExt_Py))
            if not CFile.file_or_path_exist(module_file_name):
                message = '第三方模块[{0}]没有设置对应的算法, 直接通过!'.format(ds_app_id)
                result = CResult.merge_result(self.Success, message)
                self.update_sync_result(ds_na_id, result)
                return result

            module_obj = CObject.create_module_instance(
                CSys.get_metadata_data_access_modules_root_name(), ds_app_id,
                self.get_mission_db_id())
            if module_obj is None:
                message = '第三方模块[{0}]没有设置对应的算法, 直接通过!'.format(ds_app_id)
                result = CResult.merge_result(self.Success, message)
                self.update_sync_result(ds_na_id, result)
                return result

            module_title = CUtils.dict_value_by_name(module_obj.information(),
                                                     self.Name_Title, '')

            result = module_obj.sync(ds_object_access, ds_object_id,
                                     ds_object_name, ds_object_type, None)
            self.update_sync_result(ds_na_id, result)
            return result
        except Exception as error:
            result = CResult.merge_result(
                self.Failure,
                '与第三方模块[{0}]同步的对象: [{1}]的同步过程出现异常, 详细情况: [{2}]!'.format(
                    ds_app_id, ds_object_name, error.__str__()))
            self.update_sync_result(ds_na_id, result)
            return result
예제 #14
0
    def give_me_db(self, db_id=None) -> CDataBase:
        if db_id is None:
            rt_db_id = self.DB_Server_ID_Default
        else:
            rt_db_id = CUtils.any_2_str(db_id)

        if CUtils.equal_ignore_case(rt_db_id, ''):
            rt_db_id = self.DB_Server_ID_Default

        databases = settings.application.xpath_one(self.Name_DataBases, None)
        if databases is None:
            raise Exception('系统未配置数据库定义, 请检查修正后重试!')

        for database in databases:
            if rt_db_id == CUtils.dict_value_by_name(database, self.Name_ID, self.DB_Server_ID_Default):
                return self.create_db(database)

        raise Exception('未找到标示为[{0}]]的数据库定义!'.format(rt_db_id))
예제 #15
0
 def get_ib_schema(self, dataset_type, ib_option):
     """
     根据数据集类型, 获取系统设置中的最佳入库模式
     :param ib_option: 其他入库的特殊要求
     :param dataset_type:
     :return:
     """
     ib_schema_list = settings.application.xpath_one(
         self.Path_Setting_MetaData_InBound_Schema_Special, [])
     ib_schema_default = settings.application.xpath_one(
         self.Path_Setting_MetaData_InBound_Schema_Default, None)
     for ib_schema in ib_schema_list:
         ib_schema_id = CUtils.dict_value_by_name(ib_schema, self.Name_ID,
                                                  '')
         if CUtils.equal_ignore_case(ib_schema_id, dataset_type):
             return ib_schema
     else:
         return ib_schema_default
예제 #16
0
    def batch_qa_metadata_bus_dict(self, metadata_bus_dict: dict, qa_sat_metadata_bus_list):
        """
        批量处理json格式的业务元数据中的质检项目
        :return:
        """
        if len(metadata_bus_dict) == 0:
            return

        for qa_item in qa_sat_metadata_bus_list:
            list_result = CAudit.a_dict_element(
                CUtils.dict_value_by_name(qa_item, self.Name_ID, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Title, ''),
                CUtils.dict_value_by_name(qa_item, self.Name_Group, self.QA_Group_Data_Integrity),
                CUtils.dict_value_by_name(qa_item, self.Name_Result, self.QA_Result_Pass),
                CUtils.dict_value_by_name(metadata_bus_dict, CUtils.dict_value_by_name(qa_item, self.Name_ID, ''), ''),
                qa_item
            )
            item_result = self.get_qa_result_from_list(list_result)
            self.metadata.quality.append_metadata_bus_quality(item_result)
예제 #17
0
    def __find_module_obj(self, obj_id):
        sql_query = '''
            SELECT
                dm2_storage_file.dsfid as query_file_id,
                dm2_storage_file.dsfdirectoryid as query_directory_id,
                dm2_storage_directory.dsddirlastmodifytime as query_directory_lastmodifytime,
                dm2_storage_directory.dsdid as query_dataset_directory_id,
                dm2_storage_object.* 
            FROM
                dm2_storage_object
                LEFT JOIN dm2_storage_file on dm2_storage_file.dsf_object_id = dm2_storage_object.dsoid
                LEFT JOIN dm2_storage_directory on dm2_storage_directory.dsd_object_id = dm2_storage_object.dsoid
            WHERE
                dm2_storage_object.dsoid = '{0}'
        '''.format(obj_id)
        db_id = self._db_id  # 数据库连接标识(查询的dm2的数管库)
        dataset = CFactory().give_me_db(db_id).one_row(sql_query)
        object_id = dataset.value_by_name(0, 'dsoid', '')
        object_name = dataset.value_by_name(0, 'dsoobjectname', '')
        quality_info = dataset.value_by_name(0, 'dso_quality', '')
        quality_info_xml = CXml()
        quality_info_xml.load_xml(quality_info)  # 加载查询出来的xml

        db_id_distribution = self.DB_Server_ID_Distribution  # 同步处理的目标数据库标识id
        # 构建数据对象object对应的识别插件,获取get_information里面的Plugins_Info_Module_Distribute_Engine信息
        class_classified_obj = CObject.get_plugins_instance_by_object_id(
            db_id, object_id)
        if class_classified_obj is not None:
            plugins_info = class_classified_obj.get_information()
            obj_type_code = CUtils.dict_value_by_name(
                plugins_info, class_classified_obj.Plugins_Info_Type_Code, '')
            distribution_file_main_name = CUtils.dict_value_by_name(
                plugins_info,
                class_classified_obj.Plugins_Info_Module_Distribute_Engine,
                '')  # 对应同步文件的类名称
            # 判断同步插件文件是否存在
            access_modules_root_dir = CSys.get_metadata_data_access_modules_root_dir(
            )
            distribution_root_dir = CFile.join_file(access_modules_root_dir,
                                                    self.Name_Distribution)
            distribution_file = CFile.join_file(
                distribution_root_dir,
                '{0}.py'.format(distribution_file_main_name))
            if CFile.file_or_path_exist(distribution_file):
                # 构建同步对象
                distribution_obj = CObject.create_module_distribution_instance(
                    '{0}.{1}'.format(
                        CSys.get_metadata_data_access_modules_root_name(),
                        self.Name_Distribution), distribution_file_main_name,
                    db_id_distribution, object_id, object_name, obj_type_code,
                    quality_info_xml, dataset)
                distribution_obj.set_class_plugins(class_classified_obj)
                result = CResult.merge_result(self.Success, '数据的信息提取完成')
                return distribution_obj, result
            else:
                result = CResult.merge_result(self.Failure,
                                              '同步失败,因为本类数据的同步模块未建立')
                return None, result
        else:
            result = CResult.merge_result(self.Failure, '同步失败,因为本类数据的识别模块缺失')
            return None, result
예제 #18
0
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     """
     return [
         {
             self.Name_ID:
             'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/MISSION'
         },
         {
             self.Name_ID: 'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_Value: 'PMS'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_Value: None
         },
         {
             self.Name_ID:
             'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[1]/FRAME_LAT'
         },
         {
             self.Name_ID:
             'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[1]/FRAME_LON'
         },
         {
             self.Name_ID:
             'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[2]/FRAME_LAT'
         },
         {
             self.Name_ID:
             'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[2]/FRAME_LON'
         },
         {
             self.Name_ID:
             'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[3]/FRAME_LAT'
         },
         {
             self.Name_ID:
             'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[3]/FRAME_LON'
         },
         {
             self.Name_ID:
             'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[4]/FRAME_LAT'
         },
         {
             self.Name_ID:
             'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Source_Frame/Vertex[4]/FRAME_LON'
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID:
             'centertime',  # 影像获取时间 必填
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/START_TIME'
         },
         {
             self.Name_ID: 'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_Value: '1/4'
         },
         {
             self.Name_ID:
             'rollangle',  # 侧摆角
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Scene_Source/VIEWING_ANGLE'
         },
         {
             self.Name_ID:
             'cloudpercent',  # 云量
             self.Name_XPath:
             '/Dimap_Document/Dataset_Sources/Source_Information/Quality_Assessment'
             '/Quality_Parameter[7]/QUALITY_PARAMETER_VALUE'
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_Value: None
         },
         {
             self.Name_ID: 'copyright',  # 发布来源 从info取
             self.Name_XPath: '/Dimap_Document/Dataset_Id/COPYRIGHT'
         },
         {
             self.Name_ID:
             'publishdate',  # 发布时间 必填
             self.Name_XPath:
             '/Dimap_Document/Production/DATASET_PRODUCTION_DATE'
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: '/Dimap_Document/Dataset_Id/DATASET_NAME'
         },
         {
             self.Name_ID:
             'producttype',  # 产品类型 必填
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID: 'productattribute',  # 产品属性 必填
             self.Name_XPath: '/Dimap_Document/Production/PRODUCT_TYPE',
             self.Name_Map: {  # 映射,当取到的值为key时,将值转换为value
                 'L1B': 'L1',
                 'L2B': 'L2',
                 'L4B': 'L4'
             }
         },
         {
             self.Name_ID: 'productid',  # 产品id 默认取主文件全名
             self.Name_XPath: '/Dimap_Document/Production/JOB_ID'
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: None
         }
     ]
예제 #19
0
    def plugins_classified(cls, file_info: CDMFilePathInfoEx) -> CPlugins:
        """
        插件识别
        1. 首先检查file_info的__rule_content__中, 有无优先识别插件列表, 有则使用该列表按顺序进行识别
        1. 其次, 检查file_info的__rule_content__是否为空, 如果不为空, 则获取其类型, 如果类型不为空, 则按类型, 匹配系统配置
        1. 其次, 检查应用系统配置中, 有无对目录识别插件的特殊设置, 有则按设置中的列表进行识别
        1. 最后按系统插件目录下的顺序, 对数据进行识别
        :param file_info:
        :return:
        """
        class_classified_obj = None
        # 根据rule_content, 获取入库规则文件的特定插件列表
        if file_info.file_type == cls.FileType_Dir:
            plugin_node_list = CXml.xml_xpath(file_info.rule_content,
                                              cls.Path_MD_Rule_Plugins_Dir)
        else:
            plugin_node_list = CXml.xml_xpath(file_info.rule_content,
                                              cls.Path_MD_Rule_Plugins_File)

        if len(plugin_node_list) > 0:
            # 根据指定的插件列表, 尝试进行识别
            class_classified_obj = cls.__plugins_classified_by_plugin_node_list__(
                file_info, plugin_node_list)

            if class_classified_obj is not None:
                return class_classified_obj

        # 如果入库规则文件中没有指定插件列表, 则读取数据入库规则类型, 它==数据集类型
        rule_type = CXml.get_element_text(
            CXml.xml_xpath_one(file_info.rule_content, cls.Path_MD_Rule_Type))
        if not CUtils.equal_ignore_case(rule_type, ''):
            # 如果有数据入库规则文件, 则获取其规则类型, 匹配setting中的类型
            plugins_json_array = settings.application.xpath_one(
                cls.Path_Setting_MetaData_Plugins_Dir, None)
            if plugins_json_array is not None:
                for plugins_define in plugins_json_array:
                    key_word = CUtils.any_2_str(
                        CUtils.dict_value_by_name(plugins_define,
                                                  cls.Name_Keyword, None))
                    plugin_list = CUtils.dict_value_by_name(
                        plugins_define, cls.Name_Plugin, None)
                    if plugin_list is None:
                        continue

                    if CUtils.equal_ignore_case(key_word, rule_type):
                        class_classified_obj = cls.__plugins_classified_by_plugin_list__(
                            file_info, plugin_list)
        else:
            # 如果没有数据入库规则文件, 则通过目录, 逐一匹配setting中的类型
            file_path = file_info.file_path_with_rel_path
            plugins_json_array = settings.application.xpath_one(
                cls.Path_Setting_MetaData_Plugins_Dir, None)
            if plugins_json_array is not None:
                for plugins_define in plugins_json_array:
                    key_word = CUtils.any_2_str(
                        CUtils.dict_value_by_name(plugins_define,
                                                  cls.Name_Keyword, None))
                    plugin_list = CUtils.dict_value_by_name(
                        plugins_define, cls.Name_Plugin, None)
                    if plugin_list is None:
                        continue

                    # todo(注意) 如果关键字为空, 则表明所有子目录都优先使用设置的插件列表进行识别!!!
                    if CUtils.equal_ignore_case(key_word, ''):
                        class_classified_obj = cls.__plugins_classified_by_plugin_list__(
                            file_info, plugin_list)
                    else:
                        if CFile.subpath_in_path(CUtils.any_2_str(key_word),
                                                 file_path):
                            class_classified_obj = cls.__plugins_classified_by_plugin_list__(
                                file_info, plugin_list)

                    if class_classified_obj is not None:
                        return class_classified_obj
                    else:
                        continue

        if class_classified_obj is not None:
            return class_classified_obj
        else:
            return cls.__plugins_classified_of_directory__(file_info)
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     """
     return [
         {
             self.Name_ID: 'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath: '/Auxiliary/General/Satellite'
         },
         {
             self.Name_ID: 'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_Value: 'PMS'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogCenter/Latitude'
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogCenter/Longitude'
         },
         {
             self.Name_ID: 'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogTL/Latitude'
         },
         {
             self.Name_ID: 'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogTL/Longitude'
         },
         {
             self.Name_ID: 'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogTR/Latitude'
         },
         {
             self.Name_ID: 'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogTR/Longitude'
         },
         {
             self.Name_ID: 'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogBR/Latitude'
         },
         {
             self.Name_ID: 'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogBR/Longitude'
         },
         {
             self.Name_ID: 'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogBL/Latitude'
         },
         {
             self.Name_ID: 'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingCoordinates/ImageGeogBL/Longitude'
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centertime',  # 影像获取时间 必填
             self.Name_XPath: '/Auxiliary/Image/PAN/ImagingTime/ImagingCenterTime/UTC'
         },
         {
             self.Name_ID: 'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_Value: '0.7/1'
         },
         {
             self.Name_ID: 'rollangle',  # 侧摆角
             self.Name_XPath: '/Auxiliary/Image/PAN/Angle/Roll'
         },
         {
             self.Name_ID: 'cloudpercent',  # 云量
             self.Name_XPath: '/Auxiliary/Image/PAN/CloudCover/Average'
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_Value: None
         },
         {
             self.Name_ID: 'copyright',  # 发布来源 从info取
             self.Name_Value: CUtils.dict_value_by_name(self.get_information(), self.Plugins_Info_CopyRight, None)
         },
         {
             self.Name_ID: 'publishdate',  # 发布时间 必填
             self.Name_XPath: '/Auxiliary/General/CreateDate'
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'producttype',  # 产品类型 必填
             self.Name_Value: CUtils.dict_value_by_name(self.get_information(), self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID: 'productattribute',  # 产品属性 必填
             self.Name_XPath: '/Auxiliary/General/ProductLevel',
             self.Name_Map: {  # 映射,当取到的值为key时,将值转换为value
                 'Level1R': 'L1',
                 'Level2R': 'L2',
                 'Level4R': 'L4'
             }
         },
         {
             self.Name_ID: 'productid',  # 产品id 默认取主文件全名
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: None
         }
     ]
예제 #21
0
    def notify_object(self, inbound_id: str, access: str, memo: str, obj_id,
                      obj_name, obj_type, quality) -> str:
        """
        处理数管中识别的对象, 与第三方模块的通知
        . 如果第三方模块自行处理, 则无需继承本方法
        . 如果第三方模块可以处理, 则在本模块中, 从数据库中提取对象的信息, 写入第三方模块的数据表中, 或者调用第三方模块接口

        注意: 在本方法中, 不要用_quality_info属性, 因为外部调用方考虑的效率因素, 没有传入!!!
        @:param access 当前模块对当前对象的权限
        :return:
        """
        ds_na = CFactory().give_me_db(self._db_id).one_row(
            '''
            select dsonid, dson_notify_status
            from dm2_storage_obj_na
            where dson_app_id = :app_id 
                and dson_object_id = :object_id
            ''', {
                'app_id':
                CUtils.dict_value_by_name(self.information(), self.Name_ID,
                                          ''),
                'object_id':
                obj_id
            })
        target_notify_status = self.ProcStatus_InQueue
        if not CUtils.equal_ignore_case(access, self.DataAccess_Pass):
            target_notify_status = self.ProcStatus_Finished
        if not ds_na.is_empty():
            na_id = CUtils.any_2_str(ds_na.value_by_name(0, 'dsonid', 0))
            if (ds_na.value_by_name(0, 'dson_notify_status', self.ProcStatus_Finished) == self.ProcStatus_Finished) or \
                    (ds_na.value_by_name(0, 'dson_notify_status', self.ProcStatus_Finished) == self.ProcStatus_InQueue):
                CFactory().give_me_db(self._db_id).execute(
                    '''
                    update dm2_storage_obj_na
                    set dson_notify_status = :status
                        , dson_object_access = :object_access
                        , dson_access_memo = :object_access_memo
                        , dson_inbound_id = :inbound_id
                    where dsonid = :id 
                    ''', {
                        'id': na_id,
                        'status': target_notify_status,
                        'object_access': access,
                        'inbound_id': inbound_id,
                        'object_access_memo': memo
                    })
        else:
            CFactory().give_me_db(self._db_id).execute(
                '''
                insert into dm2_storage_obj_na(dson_app_id, dson_object_access, dson_object_id, dson_inbound_id, dson_access_memo) 
                values(:app_id, :object_access, :object_id, :inbound_id, :object_access_memo)
                ''', {
                    'app_id':
                    CUtils.dict_value_by_name(self.information(), self.Name_ID,
                                              ''),
                    'object_id':
                    obj_id,
                    'object_access':
                    access,
                    'inbound_id':
                    inbound_id,
                    'object_access_memo':
                    memo
                })

        return CResult.merge_result(
            self.Success, '对象[{0}]已经推送给模块[{1}]队列! '.format(
                obj_name,
                CUtils.dict_value_by_name(self.information(), self.Name_Title,
                                          '')))
예제 #22
0
    def _do_access(self) -> str:
        try:
            quality_info_xml = self._quality_info  # 获取质检xml
            quality_summary = self._dataset.value_by_name(0, 'dso_quality_summary', '')
            quality_summary_json = CJson()
            quality_summary_json.load_obj(quality_summary)
            access_wait_flag = self.DB_False  # 定义等待标志,为True则存在检查项目为等待
            access_forbid_flag = self.DB_False  # 定义禁止标志,为True则存在检查项目为禁止
            message = ''

            # 文件与影像质检部分
            file_qa = quality_summary_json.xpath_one('total', '')
            image_qa = quality_summary_json.xpath_one('metadata.data', '')
            if CUtils.equal_ignore_case(file_qa, self.QA_Result_Error) \
                    or CUtils.equal_ignore_case(image_qa, self.QA_Result_Error):
                message = message + '[数据与其相关文件的质检存在error!请进行修正!]'
                access_forbid_flag = self.DB_True
            elif CUtils.equal_ignore_case(file_qa, self.QA_Result_Warn) \
                    or CUtils.equal_ignore_case(image_qa, self.QA_Result_Warn):
                message = message + '[数据与其相关文件的质检存在warn!请进行检查!]'
                access_wait_flag = self.DB_True
            elif CUtils.equal_ignore_case(quality_summary, ''):
                message = message + '[数据质检未进行,可能数据存在问题!请进行检查!]'
                access_forbid_flag = self.DB_True
            else:
                pass

            for qa_name, qa_id in self.access_check_dict().items():  # 循环写好的检查列表
                # qa_id = CUtils.dict_value_by_name(access_check_dict, 'qa_id', '')  # 获取id
                qa_node = quality_info_xml.xpath_one("//item[@id='{0}']".format(qa_id))  # 查询xml中的节点
                if qa_node is not None:
                    node_result = CXml.get_attr(qa_node, self.Name_Result, '', False)  # 获取质检结果
                    if CUtils.equal_ignore_case(node_result, self.QA_Result_Pass):
                        pass
                    elif CUtils.equal_ignore_case(node_result, self.QA_Result_Warn):  # 警告则等待
                        message = message + '[业务元数据的质检中,项目{0}不符合要求,建议修正!]'.format(qa_name)
                        access_wait_flag = self.DB_True
                    else:  # 错误以及其他情况,比如'',或者为其他字段
                        message = message + '[业务元数据的质检中,项目{0}不符合要求,必须修改后方可入库!]'.format(qa_name)
                        access_forbid_flag = self.DB_True
                else:
                    message = message + '[业务元数据的质检中,没有项目{0},请进行修正!]'.format(qa_name)
                    access_forbid_flag = self.DB_True

            # 数据库部分
            access_wait_flag, access_forbid_flag, message = \
                self.db_access_check(access_wait_flag, access_forbid_flag, message)

            # 开始进行检查的结果判断
            access_flag = self.DataAccess_Pass
            if access_forbid_flag:
                access_flag = self.DataAccess_Forbid
            elif access_wait_flag:
                access_flag = self.DataAccess_Wait
            if CUtils.equal_ignore_case(message, ''):
                message = '模块可以进行访问!'

            result = CResult.merge_result(
                self.Success,
                '模块[{0}.{1}]对对象[{2}]的访问能力已经分析完毕!分析结果为:{3}'.format(
                    CUtils.dict_value_by_name(self.information(), self.Name_ID, ''),
                    CUtils.dict_value_by_name(self.information(), self.Name_Title, ''),
                    self._obj_name,
                    message
                )
            )
            return CResult.merge_result_info(result, self.Name_Access, access_flag)
        except Exception as error:
            result = CResult.merge_result(
                self.Failure,
                '模块[{0}.{1}]对对象[{2}]的访问能力的分析存在异常!详细情况: {3}!'.format(
                    CUtils.dict_value_by_name(self.information(), self.Name_ID, ''),
                    CUtils.dict_value_by_name(self.information(), self.Name_Title, ''),
                    self._obj_name,
                    error.__str__()
                )
            )
            return CResult.merge_result_info(result, self.Name_Access, self.DataAccess_Forbid)
예제 #23
0
    def classified(self):
        """
        关键字识别
        """
        super().classified()
        # 预获取需要的参数
        file_path = self.file_info.file_path
        file_main_name = self.file_info.file_main_name
        file_ext = self.file_info.file_ext

        # 预定义逻辑参数 数据文件匹配
        object_file_name_flag = False
        object_file_path_flag = False
        object_file_ext_flag = False
        object_affiliated_file_main_flag = False
        object_file_affiliated_flag = False
        object_keyword_list = self.get_classified_character_of_object_keyword()
        if len(object_keyword_list) > 0:
            for keyword_info in object_keyword_list:
                keyword_id = CUtils.dict_value_by_name(keyword_info,
                                                       self.Name_ID, None)
                regex_match = CUtils.dict_value_by_name(
                    keyword_info, self.Name_RegularExpression, '.*')
                if regex_match is None:
                    regex_match = '.*'

                if CUtils.equal_ignore_case(keyword_id, self.Name_FileName):
                    if CUtils.text_match_re(file_main_name, regex_match):
                        object_file_name_flag = True
                elif CUtils.equal_ignore_case(keyword_id, self.Name_FilePath):
                    if CUtils.text_match_re(file_path, regex_match):
                        object_file_path_flag = True
                elif CUtils.equal_ignore_case(keyword_id, self.Name_FileExt):
                    if CUtils.text_match_re(file_ext, regex_match):
                        object_file_ext_flag = True
                    else:
                        same_name_file_list = CFile.file_or_dir_fullname_of_path(
                            file_path, False,
                            '(?i)^' + file_main_name + '[.].*$',
                            CFile.MatchType_Regex)
                        if len(same_name_file_list) > 0:
                            for same_name_file in same_name_file_list:
                                same_name_file_ext = CFile.file_ext(
                                    same_name_file)
                                if CUtils.text_match_re(
                                        same_name_file_ext, regex_match):
                                    object_affiliated_file_main_flag = True
                elif CUtils.equal_ignore_case(keyword_id,
                                              self.Name_FileAffiliated):
                    affiliated_file_path = CUtils.dict_value_by_name(
                        keyword_info, self.Name_FilePath, None)
                    if affiliated_file_path is not None:
                        if CFile.find_file_or_subpath_of_path(
                                affiliated_file_path, regex_match,
                                CFile.MatchType_Regex):
                            object_file_affiliated_flag = True
                    else:
                        object_file_affiliated_flag = True

        # 预定义逻辑参数 附属文件匹配
        affiliated_file_name_flag = False
        affiliated_file_path_flag = False
        affiliated_file_ext_flag = False
        affiliated_file_main_flag = False
        affiliated_keyword_list = self.get_classified_character_of_affiliated_keyword(
        )
        if len(affiliated_keyword_list) > 0:
            for keyword_info in affiliated_keyword_list:
                keyword_id = CUtils.dict_value_by_name(keyword_info,
                                                       self.Name_ID, None)
                regex_match = CUtils.dict_value_by_name(
                    keyword_info, self.Name_RegularExpression, '.*')
                if regex_match is None:
                    regex_match = '.*'

                if CUtils.equal_ignore_case(keyword_id, self.Name_FileName):
                    if CUtils.text_match_re(file_main_name, regex_match):
                        affiliated_file_name_flag = True
                elif CUtils.equal_ignore_case(keyword_id, self.Name_FilePath):
                    if CUtils.text_match_re(file_path, regex_match):
                        affiliated_file_path_flag = True
                elif CUtils.equal_ignore_case(keyword_id, self.Name_FileExt):
                    if CUtils.text_match_re(file_ext, regex_match):
                        affiliated_file_ext_flag = True
                elif CUtils.equal_ignore_case(keyword_id, self.Name_FileMain):
                    affiliated_file_path = CUtils.dict_value_by_name(
                        keyword_info, self.Name_FilePath, None)
                    if affiliated_file_path is not None:
                        if CFile.find_file_or_subpath_of_path(
                                affiliated_file_path, regex_match,
                                CFile.MatchType_Regex):
                            affiliated_file_main_flag = True

        if object_file_name_flag and object_file_path_flag and \
                object_file_ext_flag and object_file_affiliated_flag:
            self._object_confirm = self.Object_Confirm_IKnown
            self._object_name = file_main_name
            self.set_custom_affiliated_file()
        elif affiliated_file_name_flag and affiliated_file_path_flag and \
                affiliated_file_ext_flag and affiliated_file_main_flag:
            self._object_confirm = self.Object_Confirm_IKnown_Not
            self._object_name = None
        elif object_file_name_flag and object_file_path_flag and object_affiliated_file_main_flag:
            self._object_confirm = self.Object_Confirm_IKnown_Not
            self._object_name = None
        else:
            self._object_confirm = self.Object_Confirm_IUnKnown
            self._object_name = None

        return self._object_confirm, self._object_name
예제 #24
0
 def add_file_or_path(self, file: dict):
     file_src = CUtils.dict_value_by_name(file, CResource.Name_Source, None)
     for path in file_src:
         self.__zip_obj__.write(path)
         print("把文件%s归档到压缩文件%s中" % (path, self.__file_name__))
예제 #25
0
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     self.Name_ID:字段的名称 例:self.Name_ID: 'satelliteid'
     self.Name_XPath:需要从xml中取值时的xpath 例:self.Name_XPath: '/ProductMetaData/SatelliteID'
     self.Name_Custom_Item:对于字段resolution做的个性化配置,将从配置的列表中取出最小的值
     例:self.Name_Custom_Item: ['/ProductMetaData/ImageGSDLine','/ProductMetaData/ImageGSD',4]
     self.Name_Value:不在xml取得默认值与当XPath取不到值时取的值 例 self.Name_Value: 1
     self.Name_Map:映射,当取到的值为key的值时将值转换为value
     例 self.Name_Map: {  # 映射,当取到的值为key时,将值转换为value
                                 'LEVEL1A': 'L1',
                                 'LEVEL2A': 'L2',
                                 'LEVEL4A': 'L4'
                                 # self.Name_Default: None # 没有对应的的映射使用的默认值}
     """
     return [
         {
             self.Name_ID: 'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath: '/ProductMetaData/SatelliteID'
         },
         {
             self.Name_ID: 'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_XPath: '/ProductMetaData/SensorID'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_Value: None
         },
         {
             self.Name_ID: 'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath: '/ProductMetaData/TopLeftLatitude'
         },
         {
             self.Name_ID: 'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath: '/ProductMetaData/TopLeftLongitude'
         },
         {
             self.Name_ID: 'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath: '/ProductMetaData/TopRightLatitude'
         },
         {
             self.Name_ID: 'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath: '/ProductMetaData/TopRightLongitude'
         },
         {
             self.Name_ID: 'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath: '/ProductMetaData/BottomRightLatitude'
         },
         {
             self.Name_ID: 'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath: '/ProductMetaData/BottomRightLongitude'
         },
         {
             self.Name_ID: 'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath: '/ProductMetaData/BottomLeftLatitude'
         },
         {
             self.Name_ID: 'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath: '/ProductMetaData/BottomLeftLongitude'
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centertime',  # 影像获取时间 必填
             self.Name_XPath: '/ProductMetaData/CenterTime'
         },
         {
             self.Name_ID: 'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_Custom_Item: {
                 'default': 2,
                 'Pan': '/ProductMetaData/ImageGSD'
             }
         },
         {
             self.Name_ID: 'rollangle',  # 侧摆角
             self.Name_XPath: '/ProductMetaData/RollViewingAngle'
         },
         {
             self.Name_ID: 'cloudpercent',  # 云量
             self.Name_XPath: '/ProductMetaData/CloudPercent'
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_XPath: '/ProductMetaData/OrbitID'
         },
         {
             self.Name_ID:
             'copyright',  # 发布来源 从info取
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_CopyRight, None)
         },
         {
             self.Name_ID: 'publishdate',  # 发布时间 必填
             self.Name_XPath: '/ProductMetaData/ProduceTime',
             self.Name_Value: None
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: None
         },
         {
             self.Name_ID:
             'producttype',  # 产品类型 必填
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID: 'productattribute',  # 产品属性 必填
             self.Name_XPath: '/ProductMetaData/ProductLevel',
             self.Name_Map: {  # 映射,当取到的值为key时,将值转换为value
                 'LEVEL1A': 'L1',
                 'LEVEL2A': 'L2',
                 'LEVEL4A': 'L4'
                 # self.Name_Default: None # 没有对应的的映射使用默认值
             }
         },
         {
             self.Name_ID: 'productid',  # 产品id 默认取主文件全名
             self.Name_XPath: '/ProductMetaData/ProductID'
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: None
         }
     ]
예제 #26
0
    def process(self) -> str:
        """
        在这里处理将__file_info__中记录的对象所对应的文件或目录信息, 根据tags_parser_rule的定义, 进行标签识别
        :return:
        """
        # 调用父类方法
        super().process()

        if not isinstance(self._tags_parser_rule, list):
            return CResult.merge_result(self.Failure,
                                        '标签解析规则必须是一个数组, 您的配置有误, 请检查!')

        error_list = []
        for tags_parser in self._tags_parser_rule:
            catalog = CUtils.any_2_str(
                CUtils.dict_value_by_name(tags_parser, self.Name_Catalog, ''))
            tag_field_name = CUtils.any_2_str(
                CUtils.dict_value_by_name(tags_parser, self.Name_Tag, ''))
            keyword_field_list = CUtils.dict_value_by_name(
                tags_parser, self.Name_Keyword, None)
            data_sample = CUtils.any_2_str(
                CUtils.dict_value_by_name(tags_parser, self.Name_Data_Sample,
                                          ''))
            separator = CUtils.dict_value_by_name(tags_parser,
                                                  self.Name_Separator, None)
            enable = CUtils.dict_value_by_name(tags_parser, self.Name_Enable,
                                               True)
            fuzzy_matching = CUtils.dict_value_by_name(
                tags_parser, self.Name_Fuzzy_Matching, False)

            if not enable:
                continue

            if CUtils.equal_ignore_case(tag_field_name, ''):
                continue

            if CUtils.equal_ignore_case(catalog, ''):
                continue

            if keyword_field_list is None:
                continue

            if len(keyword_field_list) == 0:
                continue

            if CUtils.equal_ignore_case(data_sample,
                                        self.Tag_DataSample_MainName):
                # 如果是主名, 则将对象名称和别名, 都以文件路径的格式, 补充在主名之后, 合并进行分类识别
                tag_data_sample_str = CFile.join_file(
                    CFile.join_file(
                        CUtils.any_2_str(self.file_info.file_main_name),
                        self.object_name), self.__file_alias_name)
            elif CUtils.equal_ignore_case(data_sample,
                                          self.Tag_DataSample_RelationPath):
                tag_data_sample_str = CUtils.any_2_str(
                    self.file_info.file_path_with_rel_path)
            else:
                # 如果是主名, 则将对象名称和别名, 都以文件路径的格式, 补充在相对路径的文件主名之后, 合并进行分类识别
                tag_data_sample_str = CFile.join_file(
                    CFile.join_file(
                        CUtils.any_2_str(
                            self.file_info.file_main_name_with_rel_path),
                        self.object_name), self.__file_alias_name)

            try:
                tag_data_sample_list = CUtils.split(tag_data_sample_str,
                                                    separator)
                self.process_tag(catalog, tag_field_name, keyword_field_list,
                                 tag_data_sample_list, fuzzy_matching)
            except Exception as error:
                error_list.append(
                    '对象[{0}]在处理标签库[{1}]分类[{2}]有误, 详细错误信息为: {3}'.format(
                        self.object_name, catalog, tag_data_sample_str,
                        error.__str__()))

        if len(error_list) == 0:
            return CResult.merge_result(
                self.Success, '文件或目录[{0}]对象业务分类解析成功完成!'.format(
                    self.file_info.file_main_name_with_rel_path))
        else:
            error_message = '文件或目录[{0}]的业务分类解析处理完毕, 但解析过程中出现了错误, 具体如下: \n'.format(
                self.file_info.file_main_name_with_rel_path)
            for error_str in error_list:
                error_message = CUtils.str_append(error_message, error_str)

            return CResult.merge_result(self.Success, error_message)
예제 #27
0
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     """
     return [
         {
             self.Name_ID: 'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath: '/MetaData/ProductInfo/SatelliteID'
         },
         {
             self.Name_ID: 'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_XPath: '/MetaData/ProductInfo/Sensor'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_XPath: '/MetaData/ProductInfo/CenterLatitude'
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_XPath: '/MetaData/ProductInfo/CenterLongitude'
         },
         {
             self.Name_ID: 'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath: '/MetaData/ProductInfo/UpperLeftLatitude'
         },
         {
             self.Name_ID: 'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath: '/MetaData/ProductInfo/UpperLeftLongitude'
         },
         {
             self.Name_ID: 'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath: '/MetaData/ProductInfo/UpperRightLatitude'
         },
         {
             self.Name_ID: 'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath: '/MetaData/ProductInfo/UpperRightLongitude'
         },
         {
             self.Name_ID: 'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath: '/MetaData/ProductInfo/LowerRightLatitude'
         },
         {
             self.Name_ID: 'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath: '/MetaData/ProductInfo/LowerRightLongitude'
         },
         {
             self.Name_ID: 'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath: '/MetaData/ProductInfo/LowerLeftLatitude'
         },
         {
             self.Name_ID: 'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath: '/MetaData/ProductInfo/LowerLeftLongitude'
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centertime',  # 影像获取时间 必填
             self.Name_XPath: '/MetaData/ProductInfo/StartTime'
         },
         {
             self.Name_ID: 'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_XPath: '/MetaData/ProductInfo/ImageRowGSD'
         },
         {
             self.Name_ID: 'rollangle',  # 侧摆角
             self.Name_XPath: '/MetaData/ProductInfo/RollSatelliteAngle'
         },
         {
             self.Name_ID: 'cloudpercent',  # 云量
             self.Name_XPath: '/MetaData/ProductInfo/CloudPercent'
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_XPath: '/MetaData/ProductInfo/OrbitID'
         },
         {
             self.Name_ID: 'copyright',  # 发布来源 从info取
             self.Name_Value: CUtils.dict_value_by_name(self.get_information(), self.Plugins_Info_CopyRight, None)
         },
         {
             self.Name_ID: 'publishdate',  # 发布时间 必填
             self.Name_XPath: '/MetaData/ProductInfo/EndTime'
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: '/MetaData/ProductInfo/SceneID'
         },
         {
             self.Name_ID: 'producttype',  # 产品类型 必填
             self.Name_Value: CUtils.dict_value_by_name(self.get_information(), self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID: 'productattribute',  # 产品属性 必填
             self.Name_XPath: '/MetaData/ProductInfo/ProductLevel'
         },
         {
             self.Name_ID: 'productid',  # 产品id 默认取主文件全名
             self.Name_XPath: '/MetaData/ProductInfo/ProductID'
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: '(?i).*MSS.*_meta.xml'
         }
     ]
예제 #28
0
    def parser_metadata_custom(self, parser: CMetaDataParser) -> str:
        """
        自定义的元数据解析, 在所有质检和其他处理之后触发
        :param parser:
        :return:
        """
        meta_data_json = parser.metadata.metadata_json()
        if meta_data_json is None:
            return CResult.merge_result(
                self.Success,
                '数据[{0}]的质检和空间等元数据解析完毕, 但子图层解析有误, 无法获取JSON格式的元数据! '.format(
                    self.file_info.file_name_with_full_path,
                )
            )

        json_data_source = meta_data_json.xpath_one('datasource', None)

        layer_list = meta_data_json.xpath_one(self.Name_Layers, None)
        if layer_list is None:
            return CResult.merge_result(
                self.Success,
                '数据[{0}]的质检和空间等元数据解析完毕, 但子图层解析有误, 元数据中无法找到layers节点! '.format(
                    self.file_info.file_name_with_full_path,
                )
            )

        mdb_ib_id = CFactory().give_me_db(self.file_info.db_server_id).one_value(
            '''
            select dso_ib_id
            from dm2_storage_object
            where dsoid = :object_id
            ''',
            {
                'object_id': parser.object_id
            }
        )

        error_message_list = []
        table = CTable()
        table.load_info(self.file_info.db_server_id, self.TableName_DM_Object)

        for layer in layer_list:
            layer_name = CUtils.dict_value_by_name(layer, self.Name_Name, '')
            if CUtils.equal_ignore_case(layer_name, ''):
                continue

            layer_alias_name = CUtils.dict_value_by_name(layer, self.Name_Description, layer_name)

            layer_metadata_json = CJson()
            layer_metadata_json.set_value_of_name('datasource', json_data_source)
            layer_metadata_json.set_value_of_name('layer_count', 1)
            layer_metadata_json.set_value_of_name('layers', [layer])
            layer_metadata_text = layer_metadata_json.to_json()

            try:
                sql_find_layer_existed = '''
                select dsoid as layer_id_existed
                from dm2_storage_object
                where upper(dsoobjectname) = upper(:layer_name)
                    and dsoparentobjid = :object_id
                '''
                layer_id_existed = CFactory().give_me_db(self.file_info.db_server_id).one_value(
                    sql_find_layer_existed,
                    {
                        'layer_name': layer_name,
                        'object_id': parser.object_id
                    }
                )
                if layer_id_existed is None:
                    layer_id_existed = CUtils.one_id()

                table.column_list.reset()
                table.column_list.column_by_name('dsoid').set_value(layer_id_existed)
                table.column_list.column_by_name('dsoobjectname').set_value(layer_name)
                table.column_list.column_by_name('dsoobjecttype').set_value(
                    CUtils.dict_value_by_name(
                        self.get_information(),
                        self.Plugins_Info_Child_Layer_Plugins_Name,
                        ''
                    )
                )
                table.column_list.column_by_name('dsodatatype').set_value(
                    CUtils.dict_value_by_name(
                        self.get_information(),
                        self.Plugins_Info_Child_Layer_Data_Type,
                        ''
                    )
                )
                table.column_list.column_by_name('dsoalphacode').set_value(CUtils.alpha_text(layer_name))
                table.column_list.column_by_name('dsoaliasname').set_value(layer_alias_name)
                table.column_list.column_by_name('dsoparentobjid').set_value(parser.object_id)
                table.column_list.column_by_name('dso_ib_id').set_value(mdb_ib_id)

                table.column_list.column_by_name('dsometadatatext').set_value(layer_metadata_text)
                table.column_list.column_by_name('dsometadatajson').set_value(layer_metadata_text)
                table.column_list.column_by_name('dsometadataparsestatus').set_value(self.ProcStatus_InQueue)
                table.column_list.column_by_name('dsotagsparsestatus').set_value(self.ProcStatus_InQueue)
                table.column_list.column_by_name('dsodetailparsestatus').set_value(self.ProcStatus_InQueue)
                result = table.save_data()
                if not CResult.result_success(result):
                    error_message_list.append(
                        '图层[{0}]的创建过程出现错误, 详细信息为: {1}'.format(
                            layer_name,
                            CResult.result_message(result)
                        )
                    )
            except Exception as error:
                error_message_list.append('图层[{0}]的创建过程出现错误, 详细信息为: {1}'.format(layer_name, error.__str__()))

        if len(error_message_list) > 0:
            return CResult.merge_result(
                self.Failure,
                '数据[{0}]的质检和空间等元数据解析完毕, 但子图层解析有误, 详细情况如下: \n{1}'.format(
                    self.file_info.file_name_with_full_path,
                    CUtils.list_2_str(error_message_list, '', '\n', '', True)
                )
            )
        else:
            return CResult.merge_result(
                self.Success,
                '数据[{0}]的自定义元数据解析完毕! '.format(
                    self.file_info.file_name_with_full_path,
                )
            )
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     """
     return [
         {
             self.Name_ID: 'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath: '/product/sourceAttributes/satellite'
         },
         {
             self.Name_ID: 'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_XPath: '/product/sourceAttributes/sensor'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centertime',  # 影像获取时间 必填
             self.Name_XPath: '/product/sourceAttributes/rawDataStartTime'
         },
         {
             self.Name_ID:
             'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_XPath:
             '/product/imageAttributes/rasterAttributes/sampledPixelSpacing'
         },
         {
             self.Name_ID:
             'rollangle',  # 侧摆角
             self.Name_XPath:
             '/product/sourceAttributes/orbitAndAttitude/attitudeInformation/attitudeAngles/roll'
         },
         {
             self.Name_ID: 'cloudpercent',  # 云量
             self.Name_Value: 0
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_XPath: None
         },
         {
             self.Name_ID:
             'copyright',  # 发布来源 从info取
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_CopyRight, None)
         },
         {
             self.Name_ID:
             'publishdate',  # 发布时间 必填
             self.Name_XPath:
             '/product/imageGenerationParameters/generalProcessingInformation/processingTime'
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: None
         },
         {
             self.Name_ID:
             'producttype',  # 产品类型 必填
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID: 'productattribute',  # 产品属性 必填
             self.Name_Value: 'L1'
         },
         {
             self.Name_ID: 'productid',  # 产品id 默认取主文件全名
             self.Name_XPath: '/product/productId'
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: None
         }
     ]
예제 #30
0
 def get_metadata_bus_configuration_list(self) -> list:
     """
     固定的列表,重写时不可缺项
     """
     return [
         {
             self.Name_ID:
             'satelliteid',  # 卫星,必填,从元数据组织定义,必须是标准命名的卫星名称
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="SPACECRAFT_ID"]'
         },
         {
             self.Name_ID:
             'sensorid',  # 传感器 必填,从元数据组织定义,必须是标准命名的传感器名称
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="SENSOR_ID"]'
         },
         {
             self.Name_ID: 'centerlatitude',  # 中心维度
             self.Name_XPath: None
         },
         {
             self.Name_ID: 'centerlongitude',  # 中心经度
             self.Name_XPath: None
         },
         {
             self.Name_ID:
             'topleftlatitude',  # 左上角维度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_UL_LAT_PRODUCT"]'
         },
         {
             self.Name_ID:
             'topleftlongitude',  # 左上角经度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_UL_LON_PRODUCT"]'
         },
         {
             self.Name_ID:
             'toprightlatitude',  # 右上角维度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_UR_LAT_PRODUCT"]'
         },
         {
             self.Name_ID:
             'toprightlongitude',  # 右上角经度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_UR_LON_PRODUCT"]'
         },
         {
             self.Name_ID:
             'bottomrightlatitude',  # 右下角维度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_LL_LAT_PRODUCT"]'
         },
         {
             self.Name_ID:
             'bottomrightlongitude',  # 右下角经度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_LL_LON_PRODUCT"]'
         },
         {
             self.Name_ID:
             'bottomleftlatitude',  # 左下角维度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_LR_LAT_PRODUCT"]'
         },
         {
             self.Name_ID:
             'bottomleftlongitude',  # 左下角经度 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="CORNER_LR_LON_PRODUCT"]'
         },
         {
             self.Name_ID: 'transformimg',  # 斜视图,可空,不用质检
             self.Name_Value: None
         },
         {
             self.Name_ID: 'centertime',  # 影像获取时间 必填
             self.Name_Custom_Item: {
                 self.Name_Time_Date:
                 '//item[@name="PRODUCT_METADATA"]//item[@name="DATE_ACQUIRED"]',
                 self.Name_Time_Time:
                 '//item[@name="PRODUCT_METADATA"]//item[@name="SCENE_CENTER_TIME"]'
             }
         },
         {
             self.Name_ID:
             'resolution',  # 分辨率(米) 对应卫星的默认值,从info里取
             self.Name_XPath:
             '//item[@name="PROJECTION_PARAMETERS"]//item[@name="GRID_CELL_SIZE_PANCHROMATIC"]'
         },
         {
             self.Name_ID:
             'rollangle',  # 侧摆角
             self.Name_XPath:
             '//item[@name="IMAGE_ATTRIBUTES"]//item[@name="ROLL_ANGLE"]'
         },
         {
             self.Name_ID:
             'cloudpercent',  # 云量
             self.Name_XPath:
             '//item[@name="IMAGE_ATTRIBUTES"]//item[@name="CLOUD_COVER"]'
         },
         {
             self.Name_ID: 'dataum',  # 坐标系 默认为null
             self.Name_Value: 'WGS_1984'
         },
         {
             self.Name_ID: 'acquisition_id',  # 轨道号
             self.Name_Value: None
         },
         {
             self.Name_ID:
             'copyright',  # 发布来源 从info取
             self.Name_XPath:
             '//item[@name="METADATA_FILE_INFO"]//item[@name="ORIGIN"]'
         },
         {
             self.Name_ID:
             'publishdate',  # 发布时间 必填
             self.Name_XPath:
             '//item[@name="METADATA_FILE_INFO"]//item[@name="FILE_DATE"]'
         },
         {
             self.Name_ID: 'remark',  # 备注 可空
             self.Name_Value: None
         },
         {
             self.Name_ID: 'productname',  # 产品名称,有的能从卫星元数据里面取,没有就不取
             self.Name_XPath: None
         },
         {
             self.Name_ID:
             'producttype',  # 产品类型 必填
             self.Name_Value:
             CUtils.dict_value_by_name(self.get_information(),
                                       self.Plugins_Info_ProductType, None)
         },
         {
             self.Name_ID:
             'productattribute',  # 产品属性 必填
             self.Name_XPath:
             '//item[@name="PRODUCT_METADATA"]//item[@name="DATA_TYPE"]'
         },
         {
             self.Name_ID:
             'productid',  # 产品id 默认取主文件全名
             self.Name_XPath:
             '//item[@name="METADATA_FILE_INFO"]//item[@name="LANDSAT_SCENE_ID"]'
         },
         {
             self.Name_ID: 'otherxml',  # 预留字段,可空,配置正则
             self.Name_Value: None
         }
     ]