From e8566818b0a65f6ee436c2270df600a389839052 Mon Sep 17 00:00:00 2001 From: xiangzihao <460888207@qq.com> Date: Wed, 26 Jun 2024 21:08:48 +0800 Subject: [PATCH] [DSIP-50][UDF Manage] Remove unused udf manage function (#16212) * Remove unused udf manage function --- .github/workflows/e2e.yml | 4 - docs/configs/docsdev.js | 8 - docs/docs/en/architecture/metadata.md | 2 - docs/docs/en/architecture/task-structure.md | 2 - .../en/contribute/frontend-development.md | 3 - docs/docs/en/guide/resource/configuration.md | 2 +- docs/docs/en/guide/resource/intro.md | 2 +- docs/docs/en/guide/resource/udf-manage.md | 45 -- docs/docs/en/guide/security/security.md | 6 +- docs/docs/en/guide/task/sql.md | 7 +- docs/docs/en/guide/upgrade/incompatible.md | 4 + docs/docs/zh/architecture/metadata.md | 2 - docs/docs/zh/architecture/task-structure.md | 2 - .../zh/contribute/frontend-development.md | 3 - docs/docs/zh/guide/resource/configuration.md | 2 +- docs/docs/zh/guide/resource/intro.md | 2 +- docs/docs/zh/guide/resource/udf-manage.md | 46 -- docs/docs/zh/guide/security/security.md | 6 +- docs/docs/zh/guide/task/sql.md | 2 - docs/docs/zh/guide/upgrade/incompatible.md | 4 + docs/img/new_ui/dev/resource/create-udf.png | Bin 80525 -> 0 bytes .../new_ui/dev/resource/demo/udf-demo01.png | Bin 16514 -> 0 bytes .../new_ui/dev/resource/demo/udf-demo02.png | Bin 83500 -> 0 bytes .../new_ui/dev/resource/demo/udf-demo03.png | Bin 135663 -> 0 bytes .../api/audit/OperatorUtils.java | 13 +- .../audit/constants/AuditLogConstants.java | 1 - .../api/audit/enums/AuditType.java | 11 - .../impl/UdfFunctionAuditOperatorImpl.java | 46 -- .../ApiFuncIdentificationConstant.java | 12 - .../api/controller/ResourcesController.java | 193 --------- .../api/controller/UsersController.java | 86 ++-- .../dolphinscheduler/api/enums/Status.java | 15 +- .../ResourcePermissionCheckServiceImpl.java | 30 +- .../api/service/UdfFuncService.java | 118 ------ .../api/service/UsersService.java | 10 - .../api/service/impl/BaseServiceImpl.java | 4 +- .../api/service/impl/UdfFuncServiceImpl.java | 399 ------------------ .../api/service/impl/UsersServiceImpl.java | 72 +--- .../main/resources/i18n/messages.properties | 16 +- .../resources/i18n/messages_en_US.properties | 16 +- .../resources/i18n/messages_zh_CN.properties | 16 +- .../controller/ResourcesControllerTest.java | 178 -------- .../api/controller/UsersControllerTest.java | 18 - .../UdfFuncPermissionCheckTest.java | 94 ----- .../api/service/UdfFuncServiceTest.java | 306 -------------- .../api/service/UsersServiceTest.java | 31 -- .../common/constants/Constants.java | 6 +- .../common/enums/AuditModelType.java | 3 - .../common/enums/AuthorizationType.java | 1 - .../common/enums/UdfType.java | 59 --- .../dolphinscheduler/dao/entity/UDFUser.java | 61 --- .../dolphinscheduler/dao/entity/UdfFunc.java | 157 ------- .../dao/mapper/DataSourceMapper.java | 4 +- .../dao/mapper/UDFUserMapper.java | 44 -- .../dao/mapper/UdfFuncMapper.java | 118 ------ .../dao/mapper/UDFUserMapper.xml | 29 -- .../dao/mapper/UdfFuncMapper.xml | 189 --------- .../dao/entity/UdfFuncTest.java | 50 --- .../dao/mapper/UDFUserMapperTest.java | 184 -------- .../dao/mapper/UdfFuncMapperTest.java | 280 ------------ .../e2e/cases/FunctionManageE2ETest.java | 188 --------- .../e2e/cases/UdfManageE2ETest.java | 229 ---------- .../pages/resource/FunctionManagePage.java | 201 --------- .../e2e/pages/resource/ResourcePage.java | 22 - .../e2e/pages/resource/UdfManagePage.java | 197 --------- .../runner/TaskExecutionContextFactory.java | 19 +- .../service/process/ProcessService.java | 3 - .../service/process/ProcessServiceImpl.java | 79 ++-- .../service/process/ProcessServiceTest.java | 2 +- .../spi/enums/ResourceType.java | 18 +- .../storage/api/AbstractStorageOperator.java | 5 +- .../hdfs/LocalStorageOperatorTest.java | 7 - .../task/api/SQLTaskExecutionContext.java | 16 +- .../plugin/task/api/enums/ResourceType.java | 2 +- .../plugin/task/api/enums/UdfType.java | 56 --- .../task/api/parameters/SqlParameters.java | 38 -- .../resource/AbstractResourceParameters.java | 3 +- .../resource/UdfFuncParameters.java | 133 ------ .../api/parameters/SqlParametersTest.java | 3 - .../task/remoteshell/RemoteShellTaskTest.java | 2 +- .../plugin/task/sql/SqlTask.java | 95 +---- .../resource/MigrateResourceService.java | 20 +- .../content/components/sidebar/index.tsx | 1 - .../content/components/user/use-dropdown.ts | 1 - .../src/layouts/content/use-dataList.ts | 16 - dolphinscheduler-ui/src/locales/en_US/menu.ts | 1 - .../src/locales/en_US/project.ts | 4 +- .../src/locales/en_US/resource.ts | 19 +- .../src/locales/en_US/security.ts | 4 - dolphinscheduler-ui/src/locales/zh_CN/menu.ts | 1 - .../src/locales/zh_CN/project.ts | 3 +- .../src/locales/zh_CN/resource.ts | 17 +- .../src/locales/zh_CN/security.ts | 4 - .../src/router/modules/resources.ts | 34 -- .../src/service/modules/resources/index.ts | 108 +---- .../src/service/modules/resources/types.ts | 15 +- .../src/service/modules/users/index.ts | 9 - .../src/service/modules/users/types.ts | 5 - dolphinscheduler-ui/src/service/service.ts | 1 - dolphinscheduler-ui/src/store/user/types.ts | 1 - dolphinscheduler-ui/src/store/user/user.ts | 7 - .../src/views/login/use-login.ts | 4 - .../src/views/password/use-update.ts | 1 - .../parameter/components/parameter-modal.tsx | 20 +- .../parameter/components/use-modal.ts | 2 +- .../src/views/projects/parameter/data_type.ts | 66 +-- .../src/views/projects/parameter/index.tsx | 18 +- .../task/components/node/fields/use-sql.ts | 2 - .../task/components/node/fields/use-udfs.ts | 62 --- .../task/components/node/format-data.ts | 11 - .../task/components/node/tasks/use-sql.ts | 1 - .../projects/task/components/node/types.ts | 3 - .../components/dag/dag-save-modal.tsx | 35 +- .../definition/components/start-modal.tsx | 116 ++--- .../resource/components/resource/index.tsx | 27 +- .../resource/table/table-action.tsx | 4 +- .../components/resource/table/use-table.ts | 9 +- .../resource/components/resource/types.ts | 2 +- .../function/components/function-modal.tsx | 284 ------------- .../udf/function/components/use-form.ts | 113 ----- .../udf/function/components/use-modal.ts | 175 -------- .../resource/udf/function/index.module.scss | 43 -- .../src/views/resource/udf/function/index.tsx | 159 ------- .../src/views/resource/udf/function/types.ts | 39 -- .../views/resource/udf/function/use-table.ts | 215 ---------- .../src/views/resource/udf/resource/index.tsx | 27 -- .../components/authorize-modal.tsx | 48 --- .../user-manage/components/use-authorize.ts | 142 +------ .../src/views/security/user-manage/types.ts | 2 - .../views/security/user-manage/use-columns.ts | 5 - 130 files changed, 282 insertions(+), 5966 deletions(-) delete mode 100644 docs/docs/en/guide/resource/udf-manage.md delete mode 100644 docs/docs/zh/guide/resource/udf-manage.md delete mode 100644 docs/img/new_ui/dev/resource/create-udf.png delete mode 100644 docs/img/new_ui/dev/resource/demo/udf-demo01.png delete mode 100644 docs/img/new_ui/dev/resource/demo/udf-demo02.png delete mode 100644 docs/img/new_ui/dev/resource/demo/udf-demo03.png delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/audit/operator/impl/UdfFunctionAuditOperatorImpl.java delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UdfFuncService.java delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/UdfFuncServiceImpl.java delete mode 100644 dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/permission/UdfFuncPermissionCheckTest.java delete mode 100644 dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/UdfFuncServiceTest.java delete mode 100644 dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/UdfType.java delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/UDFUser.java delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/UdfFunc.java delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UDFUserMapper.java delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/UdfFuncMapper.java delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UDFUserMapper.xml delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/UdfFuncMapper.xml delete mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/UdfFuncTest.java delete mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/UDFUserMapperTest.java delete mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/UdfFuncMapperTest.java delete mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/FunctionManageE2ETest.java delete mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/UdfManageE2ETest.java delete mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/resource/FunctionManagePage.java delete mode 100644 dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/resource/UdfManagePage.java delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/enums/UdfType.java delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/resource/UdfFuncParameters.java delete mode 100644 dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-udfs.ts delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/components/function-modal.tsx delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/components/use-form.ts delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/components/use-modal.ts delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/index.module.scss delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/index.tsx delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/types.ts delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/function/use-table.ts delete mode 100644 dolphinscheduler-ui/src/views/resource/udf/resource/index.tsx diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 60a2f44865..5601dbbb3f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -114,10 +114,6 @@ jobs: # class: org.apache.dolphinscheduler.e2e.cases.WorkflowSwitchE2ETest - name: FileManage class: org.apache.dolphinscheduler.e2e.cases.FileManageE2ETest - - name: UdfManage - class: org.apache.dolphinscheduler.e2e.cases.UdfManageE2ETest - - name: FunctionManage - class: org.apache.dolphinscheduler.e2e.cases.FunctionManageE2ETest - name: MysqlDataSource class: org.apache.dolphinscheduler.e2e.cases.MysqlDataSourceE2ETest - name: ClickhouseDataSource diff --git a/docs/configs/docsdev.js b/docs/configs/docsdev.js index 323e8b21d9..8039aa41f3 100644 --- a/docs/configs/docsdev.js +++ b/docs/configs/docsdev.js @@ -432,10 +432,6 @@ export default { title: 'File Manage', link: '/en-us/docs/dev/user_doc/guide/resource/file-manage.html' }, - { - title: 'UDF Manage', - link: '/en-us/docs/dev/user_doc/guide/resource/udf-manage.html' - }, { title: 'Task Group Manage', link: '/en-us/docs/dev/user_doc/guide/resource/task-group.html' @@ -1153,10 +1149,6 @@ export default { title: '文件管理', link: '/zh-cn/docs/dev/user_doc/guide/resource/file-manage.html' }, - { - title: 'UDF 管理', - link: '/zh-cn/docs/dev/user_doc/guide/resource/udf-manage.html' - }, { title: '任务组管理', link: '/zh-cn/docs/dev/user_doc/guide/resource/task-group.html' diff --git a/docs/docs/en/architecture/metadata.md b/docs/docs/en/architecture/metadata.md index b4633707f5..d2d11a8323 100644 --- a/docs/docs/en/architecture/metadata.md +++ b/docs/docs/en/architecture/metadata.md @@ -22,8 +22,6 @@ see sql files in `dolphinscheduler/dolphinscheduler-dao/src/main/resources/sql` - User can have multiple projects, user project authorization completes the relationship binding using `project_id` and `user_id` in `t_ds_relation_project_user` table. - The `user_id` in the `t_ds_projcet` table represents the user who create the project, and the `user_id` in the `t_ds_relation_project_user` table represents users who have permission to the project. -- The `user_id` in the `t_ds_resources` table represents the user who create the resource, and the `user_id` in `t_ds_relation_resources_user` represents the user who has permissions to the resource. -- The `user_id` in the `t_ds_udfs` table represents the user who create the UDF, and the `user_id` in the `t_ds_relation_udfs_user` table represents a user who has permission to the UDF. ### Project - Tenant - ProcessDefinition - Schedule diff --git a/docs/docs/en/architecture/task-structure.md b/docs/docs/en/architecture/task-structure.md index dc0b9d520a..041d753403 100644 --- a/docs/docs/en/architecture/task-structure.md +++ b/docs/docs/en/architecture/task-structure.md @@ -146,7 +146,6 @@ No.|parameter name||type|description |note 5| |type |String |database type 6| |datasource |Int |datasource id 7| |sql |String |query SQL statement -8| |udfs | String| udf functions|specify UDF function ids, separate by comma 9| |sqlType | String| SQL node type |0 for query and 1 for none-query SQL 10| |title |String | mail title 11| |receivers |String |receivers @@ -180,7 +179,6 @@ No.|parameter name||type|description |note "type":"MYSQL", "datasource":1, "sql":"select id , namge , age from emp where id = ${id}", - "udfs":"", "sqlType":"0", "title":"xxxx@xxx.com", "receivers":"xxxx@xxx.com", diff --git a/docs/docs/en/contribute/frontend-development.md b/docs/docs/en/contribute/frontend-development.md index 50f8c91fb4..47276caeaf 100644 --- a/docs/docs/en/contribute/frontend-development.md +++ b/docs/docs/en/contribute/frontend-development.md @@ -163,9 +163,6 @@ Resource Management => `http://localhost:8888/#/resource/file` ``` | File Management -| udf Management - - Resource Management - - Function management ``` Data Source Management => `http://localhost:8888/#/datasource/list` diff --git a/docs/docs/en/guide/resource/configuration.md b/docs/docs/en/guide/resource/configuration.md index 1c5b389302..4ff2ee9d8d 100644 --- a/docs/docs/en/guide/resource/configuration.md +++ b/docs/docs/en/guide/resource/configuration.md @@ -1,6 +1,6 @@ # Resource Center Configuration -- You could use `Resource Center` to upload text files, UDFs and other task-related files. +- You could use `Resource Center` to upload text files and other task-related files. - You could configure `Resource Center` to use distributed file system like [Hadoop](https://hadoop.apache.org/docs/r2.7.0/) (2.6+), [MinIO](https://github.com/minio/minio) cluster or remote storage products like [AWS S3](https://aws.amazon.com/s3/), [Alibaba Cloud OSS](https://www.aliyun.com/product/oss), [Huawei Cloud OBS](https://support.huaweicloud.com/obs/index.html) etc. - You could configure `Resource Center` to use local file system. If you deploy `DolphinScheduler` in `Standalone` mode, you could configure it to use local file system for `Resource Center` without the need of an external `HDFS` system or `S3`. - Furthermore, if you deploy `DolphinScheduler` in `Cluster` mode, you could use [S3FS-FUSE](https://github.com/s3fs-fuse/s3fs-fuse) to mount `S3` or [JINDO-FUSE](https://help.aliyun.com/document_detail/187410.html) to mount `OSS` to your machines and use the local file system for `Resource Center`. In this way, you could operate remote files as if on your local machines. diff --git a/docs/docs/en/guide/resource/intro.md b/docs/docs/en/guide/resource/intro.md index 786d71e834..fbb6c2cf43 100644 --- a/docs/docs/en/guide/resource/intro.md +++ b/docs/docs/en/guide/resource/intro.md @@ -1,5 +1,5 @@ # Resource Center Introduction -The Resource Center is typically used for uploading files, UDF functions, and task group management. For a stand-alone +The Resource Center is typically used for uploading files and task group management. For a stand-alone environment, you can select the local file directory as the upload folder (**this operation does not require Hadoop or HDFS deployment**). Of course, you can also choose to upload to Hadoop or MinIO cluster. In this case, you need to have Hadoop (2.6+) or MinIO and other related environments. diff --git a/docs/docs/en/guide/resource/udf-manage.md b/docs/docs/en/guide/resource/udf-manage.md deleted file mode 100644 index c7235900cc..0000000000 --- a/docs/docs/en/guide/resource/udf-manage.md +++ /dev/null @@ -1,45 +0,0 @@ -# UDF Manage - -## Resource Management - -- The resource management and file management functions are similar. The difference is that the resource management is the UDF upload function, and the file management uploads the user programs, scripts and configuration files. -- It mainly includes the following operations: rename, download, delete, etc. -- Upload UDF resources: Same as uploading files. - -## Function Management - -### Create UDF function - -Click `Create UDF Function`, enter the UDF function parameters, select the UDF resource, and click `Submit` to create the UDF function. -Currently only temporary UDF functions for HIVE are supported. - -- UDF function name: Enter the name of the UDF function. -- Package name Class name: Enter the full path of the UDF function. -- UDF resource: Set the resource file corresponding to the created UDF function. - -![create-udf](../../../../img/new_ui/dev/resource/create-udf.png) - -## Example - -### Write UDF functions - -Users can customize the desired UDF function according to actual production requirements. Here's a function that appends "HelloWorld" to the end of any string. As shown below: - -![code-udf](../../../../img/new_ui/dev/resource/demo/udf-demo01.png) - -### Configure the UDF function - -Before configuring UDF functions, you need to upload the required function jar package through resource management. Then enter the function management and configure the relevant information. As shown below: - -![conf-udf](../../../../img/new_ui/dev/resource/demo/udf-demo02.png) - -### Use UDF functions - -In the process of using UDF functions, users only need to pay attention to the specific function writing, and upload the configuration through the resource center. The system will automatically configure the create function statement, refer to the following: [SqlTask](https://github.com/apache/dolphinscheduler/blob/923f3f38e3271d7f1d22b3abc3497cecb6957e4a/dolphinscheduler-task-plugin/dolphinscheduler-task-sql/src/main/java/org/apache/dolphinscheduler/plugin/task/sql/SqlTask.java#L507-L531) - -Enter the workflow to define an SQL node, the data source type is HIVE, and the data source instance type is HIVE/IMPALA. - -- SQL statement: `select HwUdf("abc");` This function is used in the same way as the built-in functions, and can be accessed directly using the function name. -- UDF function: Select the one configured for the resource center. - -![use-udf](../../../../img/new_ui/dev/resource/demo/udf-demo03.png) diff --git a/docs/docs/en/guide/security/security.md b/docs/docs/en/guide/security/security.md index d892571b29..646243a964 100644 --- a/docs/docs/en/guide/security/security.md +++ b/docs/docs/en/guide/security/security.md @@ -103,8 +103,8 @@ public void doPOSTParam()throws Exception{ ## Granted Permissions -* Granted permissions include project permissions, resource permissions, data source permissions, and UDF function permissions. -* Administrators can authorize projects, resources, data sources, and UDF functions that ordinary users do not create. Because the authorization methods of projects, resources, data sources and UDF functions are all the same, the project authorization is used as an example to introduce. +* Granted permissions include project permissions, resource permissions, data source permissions. +* Administrators can authorize projects, resources, data sources that ordinary users do not create. Because the authorization methods of projects, resources, data sources are all the same, the project authorization is used as an example to introduce. * Note: For projects created by the user, the user has all permissions. Therefore, permission changes to projects created by users themselves are not valid. - The administrator enters the `Security Center -> User Management` page, and clicks the "Authorize" button of the user to be authorized, as shown in the following figure: @@ -118,7 +118,7 @@ public void doPOSTParam()throws Exception{ ![no-permission-error](../../../../img/new_ui/dev/security/no-permission-error.png) -- Resources, data sources, and UDF function authorization are the same as project authorization. +- Resources, data sources authorization are the same as project authorization. ## Worker Grouping diff --git a/docs/docs/en/guide/task/sql.md b/docs/docs/en/guide/task/sql.md index 0cf2d98f5e..08f4e92392 100644 --- a/docs/docs/en/guide/task/sql.md +++ b/docs/docs/en/guide/task/sql.md @@ -21,12 +21,11 @@ Refer to [datasource-setting](../howto/datasource-setting.md) `DataSource Center - Please refer to [DolphinScheduler Task Parameters Appendix](appendix.md) `Default Task Parameters` section for default parameters. | **Parameter** | **Description** | -|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---| | Data source | Select the corresponding DataSource. | | SQL type | Supports query and non-query.
>nCH`?IVf!8OxGX~?EP?kHuVK*439FYBk*`pwfJl$*?ClWGmhz=Y
z937(3E6^kB9P-u?))NR9g?66o4ys)!-S|*I>kH)U2ci>_*AYKG-M=ah@tE$hJk(h9
z_;~-#{STX-A1BRs&K5zLx5i>n!K|6MDmcw*GO`lEWTuTpAOaFng2t<0`&U_Y*75BU
z0I-Tm;}1}6`dVg7fh2u$F8K>AbB)8rD|1`@xS|4BJyfL~GGAIjKhL{SpB
zJ>HUK7MvqxFa$<9p?0YfbO *I2+UtA>E}*k57qC!WBx~F>A3(`WYLAq%>x1L;|~6*Ypw|6OdHGZMnRwC_1Fp&ig64
z92uO$#l2xOQ_woUp&g<@dViQXq=FfDi`niH`EMmPTx++Ws8X=k&_M#FM6S-xcST&$
z;LARy(|nP}8Z7yIIsG=0KO+{;&A2#Kq}PMqD=q5*DFh-pHs4y
2-)pd?t)-R&o
z7{9XoX||_p-HCWY3PE|~ov)Pg)u5?zk}7i(Au9FqGYmWZ>hp-){*UiXJ=ghXNcBsR
zFInXLrJ48;hWd2_e`6h}#d}+Cg~qglm5TBL68d=k3!!aF8ibZ#9PE{#Gc%zaGWi@1
zjmFoa2N`oL{8Ve}>}Wlce}^A
3