From c186d894ecb8384e105d1458b7e5470ae34d8d93 Mon Sep 17 00:00:00 2001 From: "Chen, Li" Date: Fri, 19 Dec 2025 14:19:18 +0800 Subject: [PATCH] init --- .gitignore | 33 + Dockerfile | 7 + mvnw | 316 + mvnw.cmd | 188 + pom.xml | 289 + .../mdmds/MdmdsProdBsApplication.java | 17 + .../volkswagen/mdmds/aop/RequestSecurity.java | 104 + .../volkswagen/mdmds/config/BeanConfig.java | 27 + .../CustomAuthenticationEntryPoint.java | 36 + .../config/CustomBearerTokenResolver.java | 46 + .../mdmds/config/DTConfiguration.java | 24 + .../mdmds/config/HWConfiguration.java | 22 + .../volkswagen/mdmds/config/JapConfig.java | 21 + .../mdmds/config/JwtAuthConverter.java | 140 + .../config/JwtAuthConverterProperties.java | 20 + .../mdmds/config/JwtAuthenticationFilter.java | 105 + .../mdmds/config/MSConfiguration.java | 24 + .../mdmds/config/MyMariaCustomDialect.java | 10 + .../mdmds/config/OpenApiConfig.java | 45 + .../mdmds/config/VWACConfiguration.java | 24 + .../mdmds/config/WebSecurityConfig.java | 75 + .../exception/MdmdsControllerAdvice.java | 66 + .../config/exception/MdmdsException.java | 19 + .../volkswagen/mdmds/constant/CommonEnum.java | 5 + .../mdmds/constant/CommonField.java | 61 + .../mdmds/consumer/VersionDataConsumer.java | 77 + .../mdmds/consumer/VersionOuterClass.java | 865 +++ .../controller/AttributeMgmtController.java | 152 + .../mdmds/controller/GroupMgmtController.java | 257 + .../controller/PermissionMgmtController.java | 291 + .../controller/PolicyMgmtController.java | 117 + .../mdmds/controller/TestController.java | 71 + .../controller/TicketMgmtController.java | 147 + .../mdmds/controller/VehicleController.java | 55 + .../mdmds/controller/api/AttributeApi.java | 138 + .../mdmds/controller/api/GroupApi.java | 174 + .../mdmds/controller/api/PermissionApi.java | 151 + .../mdmds/controller/api/PolicyApi.java | 111 + .../mdmds/controller/api/TicketApi.java | 127 + .../mdmds/controller/api/VehicleApi.java | 55 + .../mdmds/model/dto/AttrWithValuesDTO.java | 19 + .../mdmds/model/dto/AttributeDTO.java | 24 + .../volkswagen/mdmds/model/dto/AuditDTO.java | 29 + .../volkswagen/mdmds/model/dto/DccDTO.java | 50 + .../mdmds/model/dto/DicResourceDTO.java | 16 + .../volkswagen/mdmds/model/dto/EventDTO.java | 20 + .../mdmds/model/dto/GroupBriefInfoDTO.java | 39 + .../mdmds/model/dto/GroupDetailInfoDTO.java | 36 + .../mdmds/model/dto/GroupParamsDTO.java | 25 + .../mdmds/model/dto/GroupReturnDTO.java | 27 + .../mdmds/model/dto/GroupVehicleDTO.java | 25 + .../model/dto/GroupVehicleResultDTO.java | 12 + .../mdmds/model/dto/MappingAllFieldDTO.java | 16 + .../mdmds/model/dto/MappingFieldDTO.java | 18 + .../mdmds/model/dto/PolicyBaseDTO.java | 21 + .../mdmds/model/dto/PolicyBriefInfoDTO.java | 43 + .../mdmds/model/dto/PolicyParamsDTO.java | 10 + .../mdmds/model/dto/ResourceInfoDTO.java | 17 + .../mdmds/model/dto/ResponseDTO.java | 51 + .../mdmds/model/dto/RoleInfoDTO.java | 30 + .../model/dto/RoleResourceDetailDTO.java | 17 + .../mdmds/model/dto/TicketBriefInfoDTO.java | 36 + .../mdmds/model/dto/TicketDetailDTO.java | 31 + .../mdmds/model/dto/TicketParamsDTO.java | 21 + .../mdmds/model/dto/TicketVehicleDTO.java | 21 + .../model/dto/TicketVehicleResultDTO.java | 12 + .../mdmds/model/dto/UploadDataDTO.java | 22 + .../mdmds/model/dto/UserInfoDTO.java | 34 + .../mdmds/model/dto/UserSessionDTO.java | 21 + .../mdmds/model/dto/VehicleInfoDTO.java | 14 + .../mdmds/model/dto/VehicleParamsDTO.java | 16 + .../mdmds/model/dto/VehicleReturnDTO.java | 18 + .../mdmds/model/entity/AuditLog.java | 41 + .../mdmds/model/entity/BaseEntity.java | 44 + .../model/entity/DataCollectionConfig.java | 48 + .../mdmds/model/entity/DicAttrValueEnum.java | 21 + .../mdmds/model/entity/DicResource.java | 38 + .../mdmds/model/entity/DicVehicleAttr.java | 22 + .../model/entity/DicVehicleAttrAdapter.java | 22 + .../model/entity/GroupConfiguration.java | 36 + .../mdmds/model/entity/GroupDccRecord.java | 38 + .../model/entity/GroupSpecification.java | 31 + .../mdmds/model/entity/GroupVehicle.java | 46 + .../mdmds/model/entity/ItemStatus.java | 11 + .../mdmds/model/entity/RoleInfo.java | 24 + .../volkswagen/mdmds/model/entity/Ticket.java | 35 + .../mdmds/model/entity/TicketVehicle.java | 45 + .../mdmds/model/entity/UserInfo.java | 56 + .../mdmds/model/entity/VehicleGroup.java | 37 + .../mdmds/model/entity/VehicleInfo.java | 45 + .../excel/VehicleAttributeAdapterField.java | 18 + .../model/excel/VehicleAttributeField.java | 15 + .../model/param/DataSourceAdapterParam.java | 12 + .../mdmds/model/param/DataSourceParam.java | 11 + .../mdmds/model/param/GroupCreateParam.java | 23 + .../mdmds/model/param/PolicyCreateParam.java | 40 + .../mdmds/model/param/PolicyDeleteParam.java | 13 + .../mdmds/model/param/PolicyParam.java | 14 + .../mdmds/model/param/PolicyReqParam.java | 18 + .../mdmds/model/param/PolicySaveParam.java | 33 + .../mdmds/model/param/PolicySearchParam.java | 19 + .../mdmds/model/param/RoleCreateParam.java | 10 + .../mdmds/model/param/TicketParam.java | 21 + .../mdmds/model/param/TicketUpdateParam.java | 16 + .../mdmds/model/param/UserStatusParam.java | 11 + .../mdmds/model/param/VehicleGroupParam.java | 22 + .../mdmds/model/pojo/DccBriefPojo.java | 21 + .../model/pojo/GroupVehicleInfoPojo.java | 21 + .../model/pojo/TicketVehicleInfoPojo.java | 21 + .../mdmds/model/vo/ExcelCheckVo.java | 32 + .../volkswagen/mdmds/model/vo/ResourceVo.java | 16 + .../mdmds/model/vo/RoleResourceTreeVo.java | 15 + .../mdmds/model/vo/RoleToResourceVo.java | 17 + .../volkswagen/mdmds/model/vo/TicketVo.java | 33 + .../mdmds/model/vo/VehicleGroupVo.java | 27 + .../com/volkswagen/mdmds/out/dto/Vehicle.java | 13 + .../mdmds/repos/AuditLogRepository.java | 13 + .../repos/DataCollectionConfigRepository.java | 24 + .../repos/DicAttrValueEnumRepository.java | 9 + .../mdmds/repos/DicResourceRepository.java | 24 + .../DicVehicleAttrAdapterRepository.java | 24 + .../mdmds/repos/DicVehicleAttrRepository.java | 34 + .../repos/GroupConfigurationRepository.java | 18 + .../mdmds/repos/GroupDccRecordRepository.java | 9 + .../repos/GroupSpecificationRepository.java | 11 + .../mdmds/repos/GroupVehicleRepository.java | 18 + .../mdmds/repos/RoleInfoRepository.java | 29 + .../mdmds/repos/TicketRepository.java | 19 + .../mdmds/repos/TicketVehicleRepository.java | 16 + .../mdmds/repos/UserInfoRepository.java | 18 + .../mdmds/repos/VehicleGroupRepository.java | 28 + .../mdmds/repos/VehicleInfoRepository.java | 19 + .../DataCollectionsConfRepoCustom.java | 18 + .../customize/GroupVehicleRepoCustom.java | 13 + .../customize/ResourceInfoRepoCustom.java | 11 + .../repos/customize/RoleInfoRepoCustom.java | 11 + .../repos/customize/TicketRepoCustom.java | 15 + .../customize/TicketVehicleRepoCustom.java | 13 + .../repos/customize/UserInfoRepoCustom.java | 11 + .../customize/VehicleGroupRepoCustom.java | 15 + .../DataCollectionsConfRepoCustomImpl.java | 138 + .../impl/GroupVehicleRepoCustomImpl.java | 54 + .../impl/ResourceInfoRepoCustomImpl.java | 50 + .../impl/RoleInfoRepoCustomImpl.java | 50 + .../customize/impl/TicketRepoCustomImpl.java | 97 + .../impl/TicketVehicleRepoCustomImpl.java | 56 + .../impl/UserInfoRepoCustomImpl.java | 48 + .../impl/VehicleGroupRepoCustomImpl.java | 106 + .../mdmds/service/AttributeService.java | 52 + .../mdmds/service/AuditService.java | 11 + .../mdmds/service/GroupService.java | 126 + .../mdmds/service/LinkDTService.java | 78 + .../mdmds/service/LinkHWService.java | 31 + .../mdmds/service/LinkMSService.java | 19 + .../mdmds/service/LinkVWACService.java | 23 + .../mdmds/service/PolicyService.java | 48 + .../mdmds/service/TicketService.java | 66 + .../volkswagen/mdmds/service/UserService.java | 39 + .../mdmds/service/VehicleService.java | 39 + .../service/impl/AttributeServiceImpl.java | 606 ++ .../mdmds/service/impl/AuditServiceImpl.java | 40 + .../mdmds/service/impl/GroupServiceImpl.java | 655 ++ .../mdmds/service/impl/LinkDTServiceImpl.java | 293 + .../mdmds/service/impl/LinkHWServiceImpl.java | 219 + .../mdmds/service/impl/LinkMSServiceImpl.java | 160 + .../service/impl/LinkVWACServiceImpl.java | 154 + .../mdmds/service/impl/PolicyServiceImpl.java | 351 ++ .../mdmds/service/impl/TicketServiceImpl.java | 343 ++ .../mdmds/service/impl/UserServiceImpl.java | 278 + .../service/impl/VehicleServiceImpl.java | 177 + .../com/volkswagen/mdmds/timer/CoreTimer.java | 51 + .../volkswagen/mdmds/utils/AntStrUtil.java | 44 + .../mdmds/utils/AntThreadPoolUtil.java | 21 + .../mdmds/utils/AuditorAwareImpl.java | 34 + .../com/volkswagen/mdmds/utils/ExcelUtil.java | 404 ++ .../com/volkswagen/mdmds/utils/IPUtil.java | 249 + .../volkswagen/mdmds/utils/MyHttpClient.java | 34 + .../mdmds/utils/MyX509TrustManager.java | 40 + .../com/volkswagen/mdmds/utils/TokenUtil.java | 49 + .../com/volkswagen/mdmds/utils/ToolUtil.java | 23 + .../mdmds/utils/annotation/ExcelField.java | 17 + src/main/proto/version.proto | 11 + src/main/resources/application-apr.yaml | 80 + src/main/resources/application-live.yaml | 80 + .../resources/application-uat_delete.yaml | 52 + src/main/resources/application.yaml | 84 + src/main/resources/application_delete.yaml | 58 + src/main/resources/bklogback-spring.xml | 75 + src/main/resources/dt/key.json | 5411 +++++++++++++++++ src/main/resources/kafka_client.p12 | Bin 0 -> 6230 bytes src/main/resources/kafka_client.pem | 116 + src/main/resources/read.txt | 0 .../resources/sql/ddl_adapter_2025425.sql | 22 + .../sql/dic_resource_202501211554.sql | 6 + .../sql/dic_vehicle_attr_202501211606.sql | 13 + .../resources/sql/role_info_202501211555.sql | 3 + .../role_info_dic_resources_202501211556.sql | 10 + .../mdmds/MdmdsProdBsApplicationTests.java | 56 + .../repos/DicVehicleAttrRepositoryTest.java | 39 + .../mdmds/service/impl/DTServiceImplTest.java | 140 + .../service/impl/VWACServiceImplTest.java | 33 + 201 files changed, 18537 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/com/volkswagen/mdmds/MdmdsProdBsApplication.java create mode 100644 src/main/java/com/volkswagen/mdmds/aop/RequestSecurity.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/BeanConfig.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/CustomAuthenticationEntryPoint.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/CustomBearerTokenResolver.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/DTConfiguration.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/HWConfiguration.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/JapConfig.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/JwtAuthConverter.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/JwtAuthConverterProperties.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/MSConfiguration.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/MyMariaCustomDialect.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/OpenApiConfig.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/VWACConfiguration.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/WebSecurityConfig.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/exception/MdmdsControllerAdvice.java create mode 100644 src/main/java/com/volkswagen/mdmds/config/exception/MdmdsException.java create mode 100644 src/main/java/com/volkswagen/mdmds/constant/CommonEnum.java create mode 100644 src/main/java/com/volkswagen/mdmds/constant/CommonField.java create mode 100644 src/main/java/com/volkswagen/mdmds/consumer/VersionDataConsumer.java create mode 100644 src/main/java/com/volkswagen/mdmds/consumer/VersionOuterClass.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/AttributeMgmtController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/GroupMgmtController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/PermissionMgmtController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/PolicyMgmtController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/TestController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/TicketMgmtController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/VehicleController.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/AttributeApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/GroupApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/PermissionApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/PolicyApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/TicketApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/controller/api/VehicleApi.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/AttrWithValuesDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/AttributeDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/AuditDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/DccDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/DicResourceDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/EventDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupBriefInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupDetailInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupParamsDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupReturnDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleResultDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/MappingAllFieldDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/MappingFieldDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/PolicyBaseDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/PolicyBriefInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/PolicyParamsDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/ResourceInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/ResponseDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/RoleInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/RoleResourceDetailDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/TicketBriefInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/TicketDetailDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/TicketParamsDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleResultDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/UploadDataDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/UserInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/UserSessionDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/VehicleInfoDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/VehicleParamsDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/dto/VehicleReturnDTO.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/AuditLog.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/BaseEntity.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/DataCollectionConfig.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/DicAttrValueEnum.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/DicResource.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttr.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttrAdapter.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/GroupConfiguration.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/GroupDccRecord.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/GroupSpecification.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/GroupVehicle.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/ItemStatus.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/RoleInfo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/Ticket.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/TicketVehicle.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/UserInfo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/VehicleGroup.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/entity/VehicleInfo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeAdapterField.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeField.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/DataSourceAdapterParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/DataSourceParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/GroupCreateParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicyCreateParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicyDeleteParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicyParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicyReqParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicySaveParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/PolicySearchParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/RoleCreateParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/TicketParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/TicketUpdateParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/UserStatusParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/param/VehicleGroupParam.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/pojo/DccBriefPojo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/pojo/GroupVehicleInfoPojo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/pojo/TicketVehicleInfoPojo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/ExcelCheckVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/ResourceVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/RoleResourceTreeVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/RoleToResourceVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/TicketVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/model/vo/VehicleGroupVo.java create mode 100644 src/main/java/com/volkswagen/mdmds/out/dto/Vehicle.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/AuditLogRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/DataCollectionConfigRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/DicAttrValueEnumRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/DicResourceRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrAdapterRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/GroupConfigurationRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/GroupDccRecordRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/GroupSpecificationRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/GroupVehicleRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/RoleInfoRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/TicketRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/TicketVehicleRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/UserInfoRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/VehicleGroupRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/VehicleInfoRepository.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/DataCollectionsConfRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/GroupVehicleRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/ResourceInfoRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/RoleInfoRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/TicketRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/TicketVehicleRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/UserInfoRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/VehicleGroupRepoCustom.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/DataCollectionsConfRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/GroupVehicleRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/ResourceInfoRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/RoleInfoRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketVehicleRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/UserInfoRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/repos/customize/impl/VehicleGroupRepoCustomImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/AttributeService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/AuditService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/GroupService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/LinkDTService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/LinkHWService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/LinkMSService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/LinkVWACService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/PolicyService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/TicketService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/UserService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/VehicleService.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/AttributeServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/AuditServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/GroupServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/LinkDTServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/LinkHWServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/LinkMSServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/LinkVWACServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/PolicyServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/TicketServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/UserServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/service/impl/VehicleServiceImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/timer/CoreTimer.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/AntStrUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/AntThreadPoolUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/AuditorAwareImpl.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/ExcelUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/IPUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/MyHttpClient.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/MyX509TrustManager.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/TokenUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/ToolUtil.java create mode 100644 src/main/java/com/volkswagen/mdmds/utils/annotation/ExcelField.java create mode 100644 src/main/proto/version.proto create mode 100644 src/main/resources/application-apr.yaml create mode 100644 src/main/resources/application-live.yaml create mode 100644 src/main/resources/application-uat_delete.yaml create mode 100644 src/main/resources/application.yaml create mode 100644 src/main/resources/application_delete.yaml create mode 100644 src/main/resources/bklogback-spring.xml create mode 100644 src/main/resources/dt/key.json create mode 100644 src/main/resources/kafka_client.p12 create mode 100644 src/main/resources/kafka_client.pem create mode 100644 src/main/resources/read.txt create mode 100644 src/main/resources/sql/ddl_adapter_2025425.sql create mode 100644 src/main/resources/sql/dic_resource_202501211554.sql create mode 100644 src/main/resources/sql/dic_vehicle_attr_202501211606.sql create mode 100644 src/main/resources/sql/role_info_202501211555.sql create mode 100644 src/main/resources/sql/role_info_dic_resources_202501211556.sql create mode 100644 src/test/java/com/volkswagen/mdmds/MdmdsProdBsApplicationTests.java create mode 100644 src/test/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepositoryTest.java create mode 100644 src/test/java/com/volkswagen/mdmds/service/impl/DTServiceImplTest.java create mode 100644 src/test/java/com/volkswagen/mdmds/service/impl/VWACServiceImplTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a87d161 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +#FROM eclipse-temurin:17.0.6_10-jre-alpine +FROM public.ecr.aws/docker/library/eclipse-temurin:17.0.16_8-jre-alpine-3.22 +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +COPY target/classes/kafka_client.p12 kafka_client.p12 +COPY target/classes/kafka_client.pem kafka_client.pem +ENTRYPOINT ["java", "-jar", "--add-opens", "java.base/java.io=ALL-UNNAMED", "/app.jar"] diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..8a8fb22 --- /dev/null +++ b/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a525723 --- /dev/null +++ b/pom.xml @@ -0,0 +1,289 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + + 3.3.13 + + + com.example + MDMDS-PROD-BS + 0.0.6 + MDMDS-PROD-BS + MDMDS-PROD-BS + + + 17 + 10.0.0 + 4.31.0 + + 10.1.45 + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.yaml + snakeyaml + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.yaml + snakeyaml + 2.0 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + com.fasterxml.jackson.core + jackson-databind + + + + + io.micrometer + micrometer-tracing-bridge-brave + + + aopalliance + aopalliance + + + + + org.postgresql + postgresql + 42.6.1 + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.commons + commons-compress + + + org.springframework.boot + spring-boot-autoconfigure + + + com.fasterxml.jackson.core + jackson-databind + + + + + + org.springframework.security + spring-security-config + 6.1.2 + + + + org.projectlombok + lombok + 1.18.26 + provided + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.0.2 + + + org.yaml + snakeyaml + + + org.springframework.boot + spring-boot-autoconfigure + + + com.fasterxml.jackson.core + jackson-databind + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.hibernate + hibernate-validator + 8.0.0.Final + + + org.springframework.boot + spring-boot-starter-validation + + + org.modelmapper + modelmapper + 3.1.0 + + + com.querydsl + querydsl-apt + jakarta + 5.0.0 + + + com.querydsl + querydsl-jpa + jakarta + 5.0.0 + + + org.springframework.boot + spring-boot-starter-security + + + spring-security-config + org.springframework.security + + + + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + spring-security-config + org.springframework.security + + + nimbus-jose-jwt + com.nimbusds + + + + + nimbus-jose-jwt + com.nimbusds + 9.37.2 + + + com.auth0 + java-jwt + 3.11.0 + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.fasterxml.jackson.core + jackson-databind + 2.14.0-rc2 + + + com.google.guava + guava + 32.0.1-jre + + + com.google.code.gson + gson + 2.10.1 + + + + com.alibaba + fastjson + 1.2.83 + + + com.alibaba + easyexcel + 3.3.2 + + + org.apache.commons + commons-compress + + + + + org.apache.commons + commons-compress + 1.21 + + + org.springframework.kafka + spring-kafka + + + kafka-clients + org.apache.kafka + + + + + org.apache.kafka + kafka-clients + 3.9.1 + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.1.1 + + + org.apache.maven.plugins + maven-site-plugin + 3.8.2 + + + + + + + aliyun-maven + 阿里云公共仓库 + https://maven.aliyun.com/repository/public + + true + + + true + + + + + diff --git a/src/main/java/com/volkswagen/mdmds/MdmdsProdBsApplication.java b/src/main/java/com/volkswagen/mdmds/MdmdsProdBsApplication.java new file mode 100644 index 0000000..2294309 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/MdmdsProdBsApplication.java @@ -0,0 +1,17 @@ +package com.volkswagen.mdmds; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableAsync +@EnableScheduling +@SpringBootApplication +public class MdmdsProdBsApplication { + + public static void main(String[] args) { + SpringApplication.run(MdmdsProdBsApplication.class, args); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/aop/RequestSecurity.java b/src/main/java/com/volkswagen/mdmds/aop/RequestSecurity.java new file mode 100644 index 0000000..b245294 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/aop/RequestSecurity.java @@ -0,0 +1,104 @@ +package com.volkswagen.mdmds.aop; + +import com.google.gson.Gson; +import com.volkswagen.mdmds.model.dto.AuditDTO; +import com.volkswagen.mdmds.service.AuditService; +import com.volkswagen.mdmds.utils.IPUtil; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.lang.reflect.Method; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Aspect +@Component +@Order(-10) +public class RequestSecurity { + + @Resource + private AuditService auditService; + + private static final Integer LOG_MESSAGE_SIZE = 1024; + + @Pointcut("execution(* com.volkswagen.mdmds.controller..*.*(..)) ") + private void requestLog() { + + } + + @Around("requestLog()") + private Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { + Object result = null; + // 请求 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if(attributes == null) { + return null; + } + HttpServletRequest request = attributes.getRequest(); + String reqURI = request.getRequestURI(); + String reqMethod = request.getMethod(); + // 请求方法名 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + String reqMethodName = method.getName(); + // 请求参数 + Object[] args = joinPoint.getArgs(); + // 封装日志对象 + AuditDTO auditDTO = new AuditDTO(); + auditDTO.setReqIP(IPUtil.getIpAddress(request)); + auditDTO.setReqURI(reqURI); + auditDTO.setReqMethod(reqMethod); + auditDTO.setReqMethodName(reqMethodName); + String reqParams = getJsonString(args); + auditDTO.setReqParams(reqParams.length() > LOG_MESSAGE_SIZE ? reqParams.substring(0, LOG_MESSAGE_SIZE) : reqParams); + // 执行请求 + Instant startTime = Instant.now(); + auditDTO.setStartTime(Date.from(startTime)); + try { + result = joinPoint.proceed(); + Instant endTime = Instant.now(); + auditDTO.setEndTime(Date.from(endTime)); + auditService.insertOne(auditDTO); + } catch (Throwable throwable) { + String log = throwable.getMessage(); + if(log != null) { + auditDTO.setLog(log.length() > LOG_MESSAGE_SIZE ? log.substring(0, LOG_MESSAGE_SIZE) : log); + } else { + auditDTO.setLog(""); + } + Instant endTime = Instant.now(); + auditDTO.setEndTime(Date.from(endTime)); + auditService.insertOne(auditDTO); + throw throwable; + } + + return result; + } + + private String getJsonString(Object[] args) { + Gson gson = new Gson(); + //遍历所有参数,判断参数的对象是不是包内的和基础对象,不是的话就不用序列化了 + List list = new ArrayList<>(); + for (Object arg : args) { + if (arg != null && StringUtils.startsWithAny(arg.getClass().getName(),"com.volkswagen.mdmds","java.lang")) { + list.add(arg); + } else { + list.add(null); + } + } + return gson.toJson(list); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/BeanConfig.java b/src/main/java/com/volkswagen/mdmds/config/BeanConfig.java new file mode 100644 index 0000000..d3889ea --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/BeanConfig.java @@ -0,0 +1,27 @@ +package com.volkswagen.mdmds.config; + +import org.modelmapper.ModelMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@Configuration +public class BeanConfig { + + @Bean + public ModelMapper modelMapper() { + return new ModelMapper(); + } + + @Bean + public ExecutorService httpFixedExecutors() { + return Executors.newFixedThreadPool(5); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/CustomAuthenticationEntryPoint.java b/src/main/java/com/volkswagen/mdmds/config/CustomAuthenticationEntryPoint.java new file mode 100644 index 0000000..ab6cb24 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/CustomAuthenticationEntryPoint.java @@ -0,0 +1,36 @@ +package com.volkswagen.mdmds.config; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author Shuo Ding + * @since 2023/3/7 + */ +@Component("myAuthenticationEntryPoint") +public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + OutputStream responseStream = response.getOutputStream(); + ObjectMapper mapper = new ObjectMapper(); + JSONObject result = new JSONObject(); + result.put("code", HttpStatus.UNAUTHORIZED.value()); + result.put("message", HttpStatus.UNAUTHORIZED.getReasonPhrase()); + mapper.writeValue(responseStream, result); + responseStream.flush(); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/config/CustomBearerTokenResolver.java b/src/main/java/com/volkswagen/mdmds/config/CustomBearerTokenResolver.java new file mode 100644 index 0000000..03a2aa3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/CustomBearerTokenResolver.java @@ -0,0 +1,46 @@ +package com.volkswagen.mdmds.config; + +import com.nimbusds.jose.Payload; +import com.nimbusds.jwt.SignedJWT; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException; +import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; +import org.springframework.stereotype.Component; + +import java.text.ParseException; +import java.util.Base64; + +@Slf4j +@Component +@RequiredArgsConstructor +public class CustomBearerTokenResolver implements BearerTokenResolver { + + private final JwtAuthConverterProperties properties; + + @Override + public String resolve(HttpServletRequest request) { + // 从请求头中获取 Authorization 头 + String authorization = request.getHeader("Authorization"); + if(authorization==null){ + return null; + } + String tokenValue = new String(Base64.getDecoder().decode(authorization)); + + if (tokenValue.isEmpty()) { + return null; + } + + // 检查是否以 "Bearer" 开头 + if (tokenValue.startsWith("Bearer ")) { + return tokenValue.substring(7); // 去掉 "Bearer " 前缀 + } + + throw new InvalidBearerTokenException("Invalid Bearer token format"); + } + + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/DTConfiguration.java b/src/main/java/com/volkswagen/mdmds/config/DTConfiguration.java new file mode 100644 index 0000000..065f332 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/DTConfiguration.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author Shuo Ding + * @since 2023/3/22 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "dt-api") +public class DTConfiguration { + private String url; + private String oauthUrl; + private String authType; + + private String clientId; + private String clientSecret; + private String scope; + private String grantType; + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/HWConfiguration.java b/src/main/java/com/volkswagen/mdmds/config/HWConfiguration.java new file mode 100644 index 0000000..c951dec --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/HWConfiguration.java @@ -0,0 +1,22 @@ +package com.volkswagen.mdmds.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "hw-api") +public class HWConfiguration { + + private String url; + private String oauthUrl; + + private Integer clientId; + private String clientSecret; + private String grantType; + private String scopes; + + + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/JapConfig.java b/src/main/java/com/volkswagen/mdmds/config/JapConfig.java new file mode 100644 index 0000000..b591ffa --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/JapConfig.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.config; + +import com.volkswagen.mdmds.utils.AuditorAwareImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +/** + * @author Shuo Ding + * @since 2023/2/8 + */ +@Configuration +@EnableJpaAuditing(auditorAwareRef = "auditorAware") +public class JapConfig { + + @Bean + public AuditorAware auditorAware() { + return new AuditorAwareImpl(); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverter.java b/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverter.java new file mode 100644 index 0000000..594b228 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverter.java @@ -0,0 +1,140 @@ +package com.volkswagen.mdmds.config; + + + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.entity.DicResource; +import com.volkswagen.mdmds.model.entity.RoleInfo; +import com.volkswagen.mdmds.repos.RoleInfoRepository; +import jakarta.annotation.Resource; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.jwt.JwtClaimNames; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Shuo Ding + * @since 2023/3/3 + */ +@Component +public class JwtAuthConverter implements Converter { + private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); + private final JwtAuthConverterProperties properties; + + @Resource + private RoleInfoRepository roleInfoRepository; + + public JwtAuthConverter(JwtAuthConverterProperties properties) { + this.properties = properties; + } + + @Override + public AbstractAuthenticationToken convert(Jwt jwt) { + Collection grantedAuthorities = jwtGrantedAuthoritiesConverter.convert(jwt); + if(grantedAuthorities == null) { + throw new MdmdsException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), HttpStatus.INTERNAL_SERVER_ERROR); + } + Collection authorities = Stream.concat( + grantedAuthorities.stream(), + extractResourceRoles(jwt).stream()).collect(Collectors.toSet()); + return new JwtAuthenticationToken(jwt, authorities, getPrincipalClaimName(jwt)); + } + + private String getPrincipalClaimName(Jwt jwt) { + String claimName = JwtClaimNames.SUB; + if (properties.getPrincipalAttribute() != null) { + claimName = properties.getPrincipalAttribute(); + } + return jwt.getClaim(claimName); + } + + /** + * 用来从JWT中提取角色信息 + * @param jwt + * @return + */ + private Collection extractResourceRoles(Jwt jwt) { + //idp用的realm角色 + /** + * "realm_access": { + * "roles": [ + * "CLOUDIDP_EHR_ADMIN" + * ] + */ + Set roleGrant = new HashSet<>(); + if(jwt.hasClaim("resource_access")) { + // 公司内部测试认证平台 +// addRoleGrantInner(jwt, roleGrant); + // 个人测试认证平台 + addRoleGrantIDP(jwt, roleGrant); + } else { + // IDP认证平台 + addRoleGrantIDP(jwt, roleGrant); + } + return roleGrant; + } + + private void addRoleGrantInner(Jwt jwt, Set roleGrant) { + Map resourceAccess = jwt.getClaim("resource_access"); + if (resourceAccess != null && resourceAccess.containsKey(properties.getResourceId())) { + Map resource = (Map) resourceAccess.get(properties.getResourceId()); + if(resource != null) { + List resourceRoles = (List) resource.get(CommonField.RES_ROLES); + // 查询IDP角色对应的系统角色 + Set innerRoleSet = assembleInnerRoleName(resourceRoles); + if(!innerRoleSet.isEmpty()) { + Set collect = innerRoleSet.stream().map(role -> new SimpleGrantedAuthority(CommonField.ROLE_PREFIX + role)).collect(Collectors.toSet()); + roleGrant.addAll(collect); + } + } + } + } + + private Set assembleInnerRoleName(List roleNameList) { + Set innerRoleSet = new HashSet<>(); +// List> roleInfoList = roleInfoRepository.findByRoleNameIn(roleNameList); + List> resources = roleInfoRepository.findResourceInRoleName(roleNameList); + for(Map item : resources) { + if(CommonField.VIEW_MENU.containsKey(item.get("resname"))) { + innerRoleSet.add(CommonField.VIEW_MENU.get(item.get("resname"))); + } + } +// for(Optional optionalRoleInfo : roleInfoList) { +// if(!optionalRoleInfo.isEmpty()) { +// String innerRole = optionalRoleInfo.get().getInnerRole(); +// if(!innerRole.isEmpty()) { +// innerRoleSet.addAll(Arrays.asList(innerRole.split(","))); +// } +// } +// } + return innerRoleSet; + } + + private void addRoleGrantIDP(Jwt jwt, Set roleGrant) { + if(jwt.hasClaim("realm_access")) { + Map realmAccess = jwt.getClaim("realm_access"); + if (realmAccess != null && realmAccess.containsKey(CommonField.RES_ROLES)) { + List realmRoles = (List) realmAccess.get(CommonField.RES_ROLES); + if (realmRoles != null) { + // 查询IDP角色对应的系统角色 + Set innerRoleSet = assembleInnerRoleName(realmRoles); + if(!innerRoleSet.isEmpty()) { + Set collect = innerRoleSet.stream().map(role -> new SimpleGrantedAuthority(CommonField.ROLE_PREFIX + role)).collect(Collectors.toSet()); + roleGrant.addAll(collect); + } + } + } + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverterProperties.java b/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverterProperties.java new file mode 100644 index 0000000..abc2363 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/JwtAuthConverterProperties.java @@ -0,0 +1,20 @@ +package com.volkswagen.mdmds.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +/** + * @author Shuo Ding + * @since 2023/3/3 + */ +@Data +@Validated +@Configuration +@ConfigurationProperties(prefix = "jwt.auth.converter") +public class JwtAuthConverterProperties { + private String resourceId; + private String principalAttribute; + private String uniqueAttribute; +} diff --git a/src/main/java/com/volkswagen/mdmds/config/JwtAuthenticationFilter.java b/src/main/java/com/volkswagen/mdmds/config/JwtAuthenticationFilter.java new file mode 100644 index 0000000..3a1ff45 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/JwtAuthenticationFilter.java @@ -0,0 +1,105 @@ +package com.volkswagen.mdmds.config; + +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.Payload; +import com.nimbusds.jwt.SignedJWT; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.controller.api.PermissionApi; +import com.volkswagen.mdmds.model.dto.UserSessionDTO; +//import com.volkswagen.mdmds.service.UserService; +//import jakarta.annotation.Resource; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + + +import java.io.IOException; +import java.text.ParseException; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + +// @Resource +// private UserService userService; + + private final JwtAuthConverterProperties properties; + + + private static Set URL_FILTER_SET = new HashSet<>(); + + static { + URL_FILTER_SET.add(PermissionApi.Constants.USER_PATH + "/login"); + URL_FILTER_SET.add(PermissionApi.Constants.USER_PATH + "/sameUserOnline"); + URL_FILTER_SET.add(PermissionApi.Constants.USER_PATH + "/logout"); + URL_FILTER_SET.add(PermissionApi.Constants.USER_PATH + "/forceLogin"); + URL_FILTER_SET.add(PermissionApi.Constants.USER_PATH + "/invalidToken"); + } + + // token 黑名单 + public static Map blackTokenMap = new ConcurrentHashMap<>(); + + public static Map userSessionMap = new HashMap<>(); + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + String requestURI = request.getRequestURI(); + String authorization = request.getHeader("Authorization"); + if(null==authorization){ + //没登录,放掉 + chain.doFilter(request, response); + return; + } + String deviceId = request.getHeader(properties.getUniqueAttribute()); + if (StringUtils.isEmpty(deviceId)) { + throw new MdmdsException("deviceId not found", HttpStatus.INTERNAL_SERVER_ERROR); + } + + String tokenValue = new String(Base64.getDecoder().decode(authorization)).replace("Bearer ",""); + if (blackTokenMap.containsKey(tokenValue) && blackTokenMap.get(tokenValue).isAfter(Instant.now())) { + throw new MdmdsException("token is invalid", HttpStatus.UNAUTHORIZED); + } + try { + SignedJWT signedJWT = SignedJWT.parse(tokenValue); + JWSHeader header = signedJWT.getHeader(); + Map headerJSONObject = header.toJSONObject(); + + Payload payload = signedJWT.getPayload(); + Map payloadJSONObject = payload.toJSONObject(); + Instant issuedAt = Instant.ofEpochSecond((long)payloadJSONObject.get("iat")); + Instant expiresAt = Instant.ofEpochSecond((long) payloadJSONObject.get("exp")); + payloadJSONObject.put(properties.getUniqueAttribute(), deviceId); + String username = (String) payloadJSONObject.get(properties.getPrincipalAttribute()); + Instant now = Instant.now(); + // 如果不包含该用户,或者该用户已过期,则添加该用户 + if (!URL_FILTER_SET.contains(requestURI)) { + if (!userSessionMap.containsKey(username) || userSessionMap.get(username).getExp().isBefore(now)) { + UserSessionDTO userSessionDTO = new UserSessionDTO(username, deviceId, expiresAt); + userSessionMap.put(username,userSessionDTO); + } else {// 判断是否为同一设备 + if (!userSessionMap.get(username).getDeviceId().equals(deviceId)) { + throw new MdmdsException("The same user is online. Procedure", HttpStatus.UNAUTHORIZED); + } + } + } + } catch (ParseException e) { + log.error("token conversion failure:{}", e.getMessage()); + throw new MdmdsException("token conversion failure:{}", HttpStatus.INTERNAL_SERVER_ERROR); + } + chain.doFilter(request, response); + } +} + + diff --git a/src/main/java/com/volkswagen/mdmds/config/MSConfiguration.java b/src/main/java/com/volkswagen/mdmds/config/MSConfiguration.java new file mode 100644 index 0000000..2783ca3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/MSConfiguration.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author Shuo Ding + * @since 2023/3/22 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "ms-api") +public class MSConfiguration { + private String url; + private String oauthUrl; + private String authType; + + private String clientId; + private String clientSecret; + private String scope; + private String grantType; + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/MyMariaCustomDialect.java b/src/main/java/com/volkswagen/mdmds/config/MyMariaCustomDialect.java new file mode 100644 index 0000000..5d95f9c --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/MyMariaCustomDialect.java @@ -0,0 +1,10 @@ +package com.volkswagen.mdmds.config; + +import org.hibernate.dialect.MariaDBDialect; + +/** + * @author Shuo Ding + * @since 2023/3/17 + */ +public class MyMariaCustomDialect extends MariaDBDialect { +} diff --git a/src/main/java/com/volkswagen/mdmds/config/OpenApiConfig.java b/src/main/java/com/volkswagen/mdmds/config/OpenApiConfig.java new file mode 100644 index 0000000..0a2b3b4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/OpenApiConfig.java @@ -0,0 +1,45 @@ +package com.volkswagen.mdmds.config; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Contact; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@Configuration +@SecurityScheme( + name = "Bearer Authentication", + type = SecuritySchemeType.HTTP, + bearerFormat = "JWT", + scheme = "bearer" +) +@OpenAPIDefinition( + info = @Info( + title = "MDMDS API", + version = "${api.version}", + contact = @Contact( + name = "Ding,Shuo", email = "shuo.ding@t-systems.com", url = "https://xx.com" + ), + termsOfService = "${tos.uri}", + description = "${api.description}" + ) +) +public class OpenApiConfig { + @Bean +// @Profile("!prod") + public GroupedOpenApi publicApi() { + return GroupedOpenApi.builder() + .group("MDMDS") + .packagesToScan("com.volkswagen.mdmds.controller") + .build(); + } + + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/VWACConfiguration.java b/src/main/java/com/volkswagen/mdmds/config/VWACConfiguration.java new file mode 100644 index 0000000..d0eac43 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/VWACConfiguration.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author Shuo Ding + * @since 2023/3/22 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "vwac-api") +public class VWACConfiguration { + private String url; + private String oauthUrl; + private String authType; + + private String clientId; + private String clientSecret; + private String scope; + private String grantType; + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/WebSecurityConfig.java b/src/main/java/com/volkswagen/mdmds/config/WebSecurityConfig.java new file mode 100644 index 0000000..399ccbc --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/WebSecurityConfig.java @@ -0,0 +1,75 @@ +package com.volkswagen.mdmds.config; + +import com.volkswagen.mdmds.constant.CommonField; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; + +/** + * @author Shuo Ding + * @since 2023/3/6 + */ +@RequiredArgsConstructor +@Configuration +@EnableWebSecurity +public class WebSecurityConfig { + public static final String ADMIN = "MDMDS_OPS"; + public static final String USER = "user"; + private final JwtAuthConverter jwtAuthConverter; + + private final CustomBearerTokenResolver customBearerTokenResolver; + private final JwtAuthenticationFilter jwtAuthenticationFilter; + + @Resource + @Qualifier("myAuthenticationEntryPoint") + private AuthenticationEntryPoint authEntryPoint; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.addFilterAfter(jwtAuthenticationFilter, BearerTokenAuthenticationFilter.class); + http.csrf().disable(); + http.authorizeHttpRequests(a -> { + a.requestMatchers("/test/anonymous", "/test/anonymous/**").permitAll(); + a.requestMatchers("/test/admin", "/test/admin/**").hasRole(CommonField.IDP_ROLE_ADMIN); + a.requestMatchers("/test/user").hasAnyRole(ADMIN, USER, CommonField.IDP_ROLE_ADMIN, CommonField.IDP_ROLE_USER); + + a.requestMatchers("/mdmds/v1/permission/user/login").permitAll(); + a.requestMatchers("/mdmds/v1/permission/user/sameUserOnline").permitAll(); + a.requestMatchers("/mdmds/v1/permission/user/logout").permitAll(); + a.requestMatchers("/mdmds/v1/permission/user/forceLogin").permitAll(); + a.requestMatchers("/mdmds/v1/permission/user/invalidToken").permitAll(); + + a.requestMatchers("/mdmds/v1/group", "/mdmds/v1/group/**", "/mdmds/v1/group/attribute/kv").hasRole(CommonField.INNER_GROUP); + + a.requestMatchers("/mdmds/v1/ticket", "/mdmds/v1/ticket/**").hasAnyRole(CommonField.INNER_TICKET); + + a.requestMatchers("/mdmds/v1/vehicle", "/mdmds/v1/vehicle/**").hasAnyRole(CommonField.INNER_GROUP, CommonField.INNER_TICKET, CommonField.INNER_CONFIGURATION); + + a.requestMatchers("/mdmds/v1/policy", "/mdmds/v1/policy/**").hasAnyRole(CommonField.INNER_CONFIGURATION); + + a.requestMatchers("/mdmds/v1/permission", "/mdmds/v1/permission/**").hasAnyRole(CommonField.INNER_PERMISSION); + + a.requestMatchers("/mdmds/v1/attribute", "/mdmds/v1/attribute/**").hasAnyRole(CommonField.INNER_DATASOURCE); + + + a.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll(); + }); + http.oauth2ResourceServer() + .bearerTokenResolver(customBearerTokenResolver) + .jwt() + .jwtAuthenticationConverter(jwtAuthConverter); + //如果JWT校验失败,则会返回指定格式的信息 + http.oauth2ResourceServer().authenticationEntryPoint(authEntryPoint); + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + return http.build(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsControllerAdvice.java b/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsControllerAdvice.java new file mode 100644 index 0000000..8492be2 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsControllerAdvice.java @@ -0,0 +1,66 @@ +package com.volkswagen.mdmds.config.exception; + +import com.volkswagen.mdmds.model.dto.ResponseDTO; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@ControllerAdvice +public class MdmdsControllerAdvice { + + @ExceptionHandler(NullPointerException.class) + public ResponseEntity handleNullPointerException(Exception ex){ + HttpStatus status=HttpStatus.NOT_FOUND; + return ResponseEntity.status(status).body(new ResponseDTO(status, ex.getMessage())); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleValidException(Exception e){ + HttpStatus httpStatus=HttpStatus.BAD_REQUEST; +// StringBuilder sb=new StringBuilder(); +// ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors() +// .forEach(x->sb.append(x.getDefaultMessage()+";")); +// return ResponseEntity.status(httpStatus).body(new ResponseDTO(httpStatus, sb.toString())); + return ResponseEntity.status(httpStatus).body(new ResponseDTO(httpStatus, "Request argument error, please check request data")); + } + + @ExceptionHandler( HttpMessageNotReadableException.class ) + public ResponseEntity handleMessageNotReadableException(Exception e){ + HttpStatus httpStatus=HttpStatus.BAD_REQUEST; + return ResponseEntity.status(httpStatus).body(new ResponseDTO(httpStatus, "Request profile error, please check request data")); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception e){ + HttpStatus httpStatus=HttpStatus.INTERNAL_SERVER_ERROR; + +// StringWriter stringWriter=new StringWriter(); +// PrintWriter printWriter=new PrintWriter(stringWriter); +// e.printStackTrace(printWriter); + +// String stackTrace=stringWriter.toString(); + return ResponseEntity.status(httpStatus) + .body(new ResponseDTO(httpStatus,e.getMessage())); + } + + @ExceptionHandler(MdmdsException.class) + public ResponseEntity handleMdmdsException(MdmdsException e){ +// StringWriter stringWriter=new StringWriter(); +// PrintWriter printWriter=new PrintWriter(stringWriter); +// e.printStackTrace(printWriter); + +// String stackTrace=stringWriter.toString(); + return ResponseEntity.status(e.getHttpStatus()) + .body(new ResponseDTO(e.getHttpStatus(),e.getMessage())); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsException.java b/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsException.java new file mode 100644 index 0000000..b3fff5d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/config/exception/MdmdsException.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.config.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +/** + * @author Shuo Ding + * @since 2023/3/7 + */ +@Getter +public class MdmdsException extends RuntimeException{ + + private final HttpStatus httpStatus; + + public MdmdsException(String message, HttpStatus httpStatus) { + super(message); + this.httpStatus = httpStatus; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/constant/CommonEnum.java b/src/main/java/com/volkswagen/mdmds/constant/CommonEnum.java new file mode 100644 index 0000000..731a16b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/constant/CommonEnum.java @@ -0,0 +1,5 @@ +package com.volkswagen.mdmds.constant; + +public enum CommonEnum { + DT_TOKEN; +} diff --git a/src/main/java/com/volkswagen/mdmds/constant/CommonField.java b/src/main/java/com/volkswagen/mdmds/constant/CommonField.java new file mode 100644 index 0000000..3cd8ff4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/constant/CommonField.java @@ -0,0 +1,61 @@ +package com.volkswagen.mdmds.constant; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CommonField { + + private CommonField() { + + } + + public static final String DT_TOKEN = "DTToken"; + public static final String VWAC_TOKEN = "VWACToken"; + public static final String HW_TOKEN = "HWToken"; + public static final String MS_TOKEN = "MSToken"; + + public static final String RES_ROLES = "roles"; + public static final String ROLE_PREFIX = "ROLE_"; + + public static final String IDP_ROLE_ADMIN = "CLOUDIDP_EHR_ADMIN"; + public static final String IDP_ROLE_USER = "CLOUDIDP_EHR_USER"; + + public static final String ADS_VERSION_FIELD = "ADS Version"; + public static final List VEHICLE_BASE_FIELDS = Arrays.asList(ADS_VERSION_FIELD, "Brand Code", "Brand Name", "Model Code", "Model Family", "Model Name", "Model Year", "Platform Name", "Platform Variant"); + + public static final String INNER_GROUP = "INNER_GROUP"; + public static final String INNER_TICKET = "INNER_TICKET"; + public static final String INNER_CONFIGURATION = "INNER_CONFIGURATION"; + public static final String INNER_PERMISSION = "INNER_PERMISSION"; + public static final String INNER_DATASOURCE = "INNER_DATASOURCE"; + + public static final String VIEW_GROUP = "Group Management"; + public static final String VIEW_TICKET = "Ticket Management"; + public static final String VIEW_CONFIGURATION = "Configuration Management"; + public static final String VIEW_PERMISSION = "Permission Management"; + public static final String VIEW_DATASOURCE = "Data Source Management"; + + public static final List COMMON_RESOURCE = Arrays.asList(INNER_GROUP, INNER_TICKET, INNER_CONFIGURATION, INNER_DATASOURCE); + + public static final Map INNER_MENU = new HashMap<>(); + static { + INNER_MENU.put(INNER_GROUP, VIEW_GROUP); + INNER_MENU.put(INNER_TICKET, VIEW_TICKET); + INNER_MENU.put(INNER_CONFIGURATION, VIEW_CONFIGURATION); + INNER_MENU.put(INNER_PERMISSION, VIEW_PERMISSION); + INNER_MENU.put(INNER_DATASOURCE, VIEW_DATASOURCE); + } + public static final Map VIEW_MENU = new HashMap<>(); + static { + VIEW_MENU.put(VIEW_GROUP, INNER_GROUP); + VIEW_MENU.put(VIEW_TICKET, INNER_TICKET); + VIEW_MENU.put(VIEW_CONFIGURATION, INNER_CONFIGURATION); + VIEW_MENU.put(VIEW_PERMISSION, INNER_PERMISSION); + VIEW_MENU.put(VIEW_DATASOURCE, INNER_DATASOURCE); + } + + public static final String VIN_ERROR = "VIN code error"; + +} diff --git a/src/main/java/com/volkswagen/mdmds/consumer/VersionDataConsumer.java b/src/main/java/com/volkswagen/mdmds/consumer/VersionDataConsumer.java new file mode 100644 index 0000000..fcc2795 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/consumer/VersionDataConsumer.java @@ -0,0 +1,77 @@ +package com.volkswagen.mdmds.consumer; + + +import com.alibaba.fastjson.JSONPath; +import com.google.protobuf.InvalidProtocolBufferException; +import com.volkswagen.mdmds.model.entity.DicVehicleAttrAdapter; +import com.volkswagen.mdmds.repos.DicVehicleAttrAdapterRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +import java.util.Base64; +import java.util.Objects; + +@Component +@Slf4j +@RequiredArgsConstructor +public class VersionDataConsumer { + + public static final String SPLIT = "_"; + + private static final String ENUM_FORMAT = "%s(%s)"; + + public static final String ATTR_NAME = "ecus/8103/sw_version"; + + private final DicVehicleAttrAdapterRepository dicVehicleAttrAdapterRepository; + + @KafkaListener(topics = "${spring.kafka.topics.version-topic}", + groupId = "${spring.kafka.groups.version-group}") + public void listen(ConsumerRecord record) { + + String payloadValue = (String) JSONPath.eval(record.value(), "$.payload.value"); + byte[] valueBytes = Base64.getDecoder().decode(payloadValue); + if (valueBytes.length > 2) { + String hex = bytesToHex(valueBytes[0]) + bytesToHex(valueBytes[1]); + char msgTypeChar = hex.charAt(3); + if (msgTypeChar == '2') { + log.info("Received message: key = {}, value = {}, partition = {}", + record.key(), record.value(), record.partition()); + byte[] protobufData = new byte[valueBytes.length - 2]; + System.arraycopy(valueBytes, 2, protobufData, 0, protobufData.length); + try { + VersionOuterClass.Version version = VersionOuterClass.Version.parseFrom(protobufData); + + String adsVersion = version.getAdsVersion(); + if (adsVersion.contains(SPLIT)) { + adsVersion = adsVersion.split(SPLIT)[0]; + } + String vwVersion = version.getVwVersion(); + String adapterMapping = String.format(ENUM_FORMAT, adsVersion, vwVersion); + DicVehicleAttrAdapter attrAdapterMapping = dicVehicleAttrAdapterRepository.findByAdapterMapping(adapterMapping); + if (Objects.isNull(attrAdapterMapping)) { + DicVehicleAttrAdapter dicVehicleAttrAdapter = new DicVehicleAttrAdapter(); + dicVehicleAttrAdapter.setAttrName(ATTR_NAME); + dicVehicleAttrAdapter.setAdapterValue(vwVersion); + dicVehicleAttrAdapter.setAdapterKey(adsVersion); + dicVehicleAttrAdapter.setAdapterMapping(adapterMapping); + dicVehicleAttrAdapterRepository.save(dicVehicleAttrAdapter); + } + } catch (InvalidProtocolBufferException e) { + throw new RuntimeException(e); + } + } + } + + } + + private static String bytesToHex(byte b) { + char[] hexChars = new char[2]; + hexChars[0] = Character.forDigit((b >> 4) & 0xF, 16); + hexChars[1] = Character.forDigit(b & 0xF, 16); + return new String(hexChars); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/consumer/VersionOuterClass.java b/src/main/java/com/volkswagen/mdmds/consumer/VersionOuterClass.java new file mode 100644 index 0000000..b320262 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/consumer/VersionOuterClass.java @@ -0,0 +1,865 @@ +package com.volkswagen.mdmds.consumer;// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: version.proto +// Protobuf Java Version: 4.31.0 + +@com.google.protobuf.Generated +public final class VersionOuterClass { + private VersionOuterClass() {} + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + VersionOuterClass.class.getName()); + } + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + public interface VersionOrBuilder extends + // @@protoc_insertion_point(interface_extends:Version) + com.google.protobuf.MessageOrBuilder { + + /** + * string adsVersion = 1; + * @return The adsVersion. + */ + String getAdsVersion(); + /** + * string adsVersion = 1; + * @return The bytes for adsVersion. + */ + com.google.protobuf.ByteString + getAdsVersionBytes(); + + /** + * string shadowVersion = 2; + * @return The shadowVersion. + */ + String getShadowVersion(); + /** + * string shadowVersion = 2; + * @return The bytes for shadowVersion. + */ + com.google.protobuf.ByteString + getShadowVersionBytes(); + + /** + * string vwVersion = 3; + * @return The vwVersion. + */ + String getVwVersion(); + /** + * string vwVersion = 3; + * @return The bytes for vwVersion. + */ + com.google.protobuf.ByteString + getVwVersionBytes(); + } + /** + * Protobuf type {@code Version} + */ + public static final class Version extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:Version) + VersionOrBuilder { + private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + Version.class.getName()); + } + // Use Version.newBuilder() to construct. + private Version(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Version() { + adsVersion_ = ""; + shadowVersion_ = ""; + vwVersion_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return VersionOuterClass.internal_static_Version_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return VersionOuterClass.internal_static_Version_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Version.class, Builder.class); + } + + public static final int ADSVERSION_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile Object adsVersion_ = ""; + /** + * string adsVersion = 1; + * @return The adsVersion. + */ + @Override + public String getAdsVersion() { + Object ref = adsVersion_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + adsVersion_ = s; + return s; + } + } + /** + * string adsVersion = 1; + * @return The bytes for adsVersion. + */ + @Override + public com.google.protobuf.ByteString + getAdsVersionBytes() { + Object ref = adsVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + adsVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SHADOWVERSION_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile Object shadowVersion_ = ""; + /** + * string shadowVersion = 2; + * @return The shadowVersion. + */ + @Override + public String getShadowVersion() { + Object ref = shadowVersion_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + shadowVersion_ = s; + return s; + } + } + /** + * string shadowVersion = 2; + * @return The bytes for shadowVersion. + */ + @Override + public com.google.protobuf.ByteString + getShadowVersionBytes() { + Object ref = shadowVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + shadowVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int VWVERSION_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile Object vwVersion_ = ""; + /** + * string vwVersion = 3; + * @return The vwVersion. + */ + @Override + public String getVwVersion() { + Object ref = vwVersion_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + vwVersion_ = s; + return s; + } + } + /** + * string vwVersion = 3; + * @return The bytes for vwVersion. + */ + @Override + public com.google.protobuf.ByteString + getVwVersionBytes() { + Object ref = vwVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + vwVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(adsVersion_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, adsVersion_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(shadowVersion_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, shadowVersion_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(vwVersion_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, vwVersion_); + } + getUnknownFields().writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(adsVersion_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, adsVersion_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(shadowVersion_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, shadowVersion_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(vwVersion_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, vwVersion_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Version)) { + return super.equals(obj); + } + Version other = (Version) obj; + + if (!getAdsVersion() + .equals(other.getAdsVersion())) return false; + if (!getShadowVersion() + .equals(other.getShadowVersion())) return false; + if (!getVwVersion() + .equals(other.getVwVersion())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ADSVERSION_FIELD_NUMBER; + hash = (53 * hash) + getAdsVersion().hashCode(); + hash = (37 * hash) + SHADOWVERSION_FIELD_NUMBER; + hash = (53 * hash) + getShadowVersion().hashCode(); + hash = (37 * hash) + VWVERSION_FIELD_NUMBER; + hash = (53 * hash) + getVwVersion().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Version parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Version parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Version parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Version parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Version parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Version parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Version parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static Version parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static Version parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static Version parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Version parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static Version parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Version prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code Version} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:Version) + VersionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return VersionOuterClass.internal_static_Version_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return VersionOuterClass.internal_static_Version_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Version.class, Builder.class); + } + + // Construct using VersionOuterClass.Version.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + adsVersion_ = ""; + shadowVersion_ = ""; + vwVersion_ = ""; + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return VersionOuterClass.internal_static_Version_descriptor; + } + + @Override + public Version getDefaultInstanceForType() { + return Version.getDefaultInstance(); + } + + @Override + public Version build() { + Version result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public Version buildPartial() { + Version result = new Version(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(Version result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.adsVersion_ = adsVersion_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.shadowVersion_ = shadowVersion_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.vwVersion_ = vwVersion_; + } + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Version) { + return mergeFrom((Version)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Version other) { + if (other == Version.getDefaultInstance()) return this; + if (!other.getAdsVersion().isEmpty()) { + adsVersion_ = other.adsVersion_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getShadowVersion().isEmpty()) { + shadowVersion_ = other.shadowVersion_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getVwVersion().isEmpty()) { + vwVersion_ = other.vwVersion_; + bitField0_ |= 0x00000004; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + adsVersion_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + shadowVersion_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + vwVersion_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private Object adsVersion_ = ""; + /** + * string adsVersion = 1; + * @return The adsVersion. + */ + public String getAdsVersion() { + Object ref = adsVersion_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + adsVersion_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string adsVersion = 1; + * @return The bytes for adsVersion. + */ + public com.google.protobuf.ByteString + getAdsVersionBytes() { + Object ref = adsVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + adsVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string adsVersion = 1; + * @param value The adsVersion to set. + * @return This builder for chaining. + */ + public Builder setAdsVersion( + String value) { + if (value == null) { throw new NullPointerException(); } + adsVersion_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * string adsVersion = 1; + * @return This builder for chaining. + */ + public Builder clearAdsVersion() { + adsVersion_ = getDefaultInstance().getAdsVersion(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + * string adsVersion = 1; + * @param value The bytes for adsVersion to set. + * @return This builder for chaining. + */ + public Builder setAdsVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + adsVersion_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private Object shadowVersion_ = ""; + /** + * string shadowVersion = 2; + * @return The shadowVersion. + */ + public String getShadowVersion() { + Object ref = shadowVersion_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + shadowVersion_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string shadowVersion = 2; + * @return The bytes for shadowVersion. + */ + public com.google.protobuf.ByteString + getShadowVersionBytes() { + Object ref = shadowVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + shadowVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string shadowVersion = 2; + * @param value The shadowVersion to set. + * @return This builder for chaining. + */ + public Builder setShadowVersion( + String value) { + if (value == null) { throw new NullPointerException(); } + shadowVersion_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string shadowVersion = 2; + * @return This builder for chaining. + */ + public Builder clearShadowVersion() { + shadowVersion_ = getDefaultInstance().getShadowVersion(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string shadowVersion = 2; + * @param value The bytes for shadowVersion to set. + * @return This builder for chaining. + */ + public Builder setShadowVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + shadowVersion_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private Object vwVersion_ = ""; + /** + * string vwVersion = 3; + * @return The vwVersion. + */ + public String getVwVersion() { + Object ref = vwVersion_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + vwVersion_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * string vwVersion = 3; + * @return The bytes for vwVersion. + */ + public com.google.protobuf.ByteString + getVwVersionBytes() { + Object ref = vwVersion_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (String) ref); + vwVersion_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string vwVersion = 3; + * @param value The vwVersion to set. + * @return This builder for chaining. + */ + public Builder setVwVersion( + String value) { + if (value == null) { throw new NullPointerException(); } + vwVersion_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * string vwVersion = 3; + * @return This builder for chaining. + */ + public Builder clearVwVersion() { + vwVersion_ = getDefaultInstance().getVwVersion(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * string vwVersion = 3; + * @param value The bytes for vwVersion to set. + * @return This builder for chaining. + */ + public Builder setVwVersionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + vwVersion_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:Version) + } + + // @@protoc_insertion_point(class_scope:Version) + private static final Version DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Version(); + } + + public static Version getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @Override + public Version parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public Version getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_Version_descriptor; + private static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_Version_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + String[] descriptorData = { + "\n\rversion.proto\"G\n\007Version\022\022\n\nadsVersion" + + "\030\001 \001(\t\022\025\n\rshadowVersion\030\002 \001(\t\022\021\n\tvwVersi" + + "on\030\003 \001(\tb\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_Version_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_Version_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_Version_descriptor, + new String[] { "AdsVersion", "ShadowVersion", "VwVersion", }); + descriptor.resolveAllFeaturesImmutable(); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/AttributeMgmtController.java b/src/main/java/com/volkswagen/mdmds/controller/AttributeMgmtController.java new file mode 100644 index 0000000..4f4fc60 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/AttributeMgmtController.java @@ -0,0 +1,152 @@ +package com.volkswagen.mdmds.controller; + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.controller.api.AttributeApi; +import com.volkswagen.mdmds.model.dto.AttrWithValuesDTO; +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.dto.UploadDataDTO; +import com.volkswagen.mdmds.model.entity.DicVehicleAttr; +import com.volkswagen.mdmds.model.excel.VehicleAttributeField; +import com.volkswagen.mdmds.service.AttributeService; +import com.volkswagen.mdmds.utils.ExcelUtil; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.BeanUtils; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@RestController +public class AttributeMgmtController implements AttributeApi { + private final AttributeService attributeService; + + public AttributeMgmtController(AttributeService attributeService) { + this.attributeService = attributeService; + } + + + @Override + public ResponseEntity> getAllAttrs() { + List allAttrs = attributeService.getAllAttrs(); + return ResponseEntity.of(Optional.ofNullable(allAttrs)); + } + + @Override + public ResponseEntity> getAttrViews(AttributeDTO attributeDTO) { + List allAttrs = attributeService.getAttrViews(attributeDTO); + return ResponseEntity.of(Optional.ofNullable(allAttrs)); + } + + @Override + public ResponseEntity addAttribute(AttributeDTO attributeDTO) { + DicVehicleAttr dicVehicleAttr = attributeService.addNewAttr(attributeDTO); + BeanUtils.copyProperties(dicVehicleAttr, attributeDTO); + return ResponseEntity.ok(attributeDTO); + } + + @Override + public ResponseEntity changeAttributeStatus(UUID id, AttributeDTO dto) { + DicVehicleAttr dicVehicleAttr = attributeService.changeAttributeStatus(id, dto); + BeanUtils.copyProperties(dicVehicleAttr, dto); + return ResponseEntity.ok(dto); + } + + @Override + public ResponseEntity deleteAttributeById(UUID id) { + DicVehicleAttr dicVehicleAttr = attributeService.deleteAttributeById(id); + if (dicVehicleAttr.getId() != null) { + return ResponseEntity.ok().build(); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity updateVehicleAttr(UUID id, AttributeDTO attributeDTO) { + DicVehicleAttr dicVehicleAttr = attributeService.updateVehicleAttr(id, attributeDTO); + if (dicVehicleAttr.getId() != null) { + BeanUtils.copyProperties(dicVehicleAttr, attributeDTO); + return ResponseEntity.ok(attributeDTO); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity clearTable() { + try { + attributeService.clearTable(); + } catch (Exception e) { + throw new MdmdsException("SQL error", HttpStatus.CONFLICT); + } + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity verification() { + try { + attributeService.verification(); + } catch (Exception ex) { + throw new MdmdsException(ex.getMessage(), HttpStatus.CONFLICT); + } + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity verificationAttrName(AttributeDTO attributeDTO) { + return ResponseEntity.ok(attributeService.verificationAttrName(attributeDTO)); + } + + @Override + public ResponseEntity getAttrValue() { + attributeService.getAttrValue(); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity> getAllAttrValueMap() { + return ResponseEntity.ok(attributeService.getAllAttrValueMap()); + } + + @Override + public ResponseEntity uploadExcel(MultipartFile file) { + attributeService.uploadAttributeFiled(file); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity uploadExcelCheck(MultipartFile file) { + return attributeService.uploadAttributeFieldCheckData(file); + } + + @Override + public ResponseEntity uploadExcelData(UploadDataDTO uploadDataDTO) { + attributeService.uploadAttribute(uploadDataDTO); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity downloadExcelTemplate(HttpServletResponse response) { + try { + ExcelUtil.createExcelTemplate(response, VehicleAttributeField.class, "VehicleAttributeField.xlsx",null); + } catch (Exception e) { + throw new MdmdsException("Excel template download error", HttpStatus.INTERNAL_SERVER_ERROR); + } + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity updateVehicleKeyAndValue(HttpServletResponse response) { + attributeService.syncVehicleKeyAndValue(); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/GroupMgmtController.java b/src/main/java/com/volkswagen/mdmds/controller/GroupMgmtController.java new file mode 100644 index 0000000..be5a84f --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/GroupMgmtController.java @@ -0,0 +1,257 @@ +package com.volkswagen.mdmds.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.controller.api.GroupApi; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.GroupSpecification; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.VehicleGroup; +import com.volkswagen.mdmds.model.param.GroupCreateParam; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import com.volkswagen.mdmds.out.dto.Vehicle; +import com.volkswagen.mdmds.repos.GroupSpecificationRepository; +import com.volkswagen.mdmds.repos.VehicleGroupRepository; +import com.volkswagen.mdmds.service.*; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@RestController +public class GroupMgmtController implements GroupApi { + + protected Logger log = LoggerFactory.getLogger(GroupMgmtController.class); + + private static final String RES_VEHICLE_VALUE = "value"; + + + @Resource + private VehicleGroupRepository vehicleGroupRepository; + @Resource + private GroupSpecificationRepository groupSpecRepository; + + @Resource + private LinkDTService linkDTService; + + private final GroupService groupService; + private final TicketService ticketService; + + public GroupMgmtController(GroupService groupService, TicketService ticketService) { + this.groupService = groupService; + this.ticketService = ticketService; + } + + @Override + public ResponseEntity createGroup(GroupCreateParam groupBriefInfoDTO) { + UUID newGroupID = groupService.createNewGroupByName(groupBriefInfoDTO.getGroupName()); + GroupBriefInfoDTO build = GroupBriefInfoDTO.builder().id(newGroupID).build(); + return ResponseEntity.ok(build); + } + + @Override + public ResponseEntity> getPageableGroup(VehicleGroupParam param) { + Page vehicleGroupVoPage = groupService.pageableGroup(param.getPageNo(), param.getPageSize(), param); + return ResponseEntity.ok(vehicleGroupVoPage); + } + + @Override + public ResponseEntity deleteGroupById(UUID id) { + groupService.deleteGroupById(id); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity deletedGroupByIds(GroupParamsDTO dto) { + groupService.deletedGroupByIds(dto.getIdList()); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getGroupDetailInfo(UUID id) { + GroupDetailInfoDTO groupDetailInfoDTO = groupService.getGroupDetailInfo(id); + return ResponseEntity.ok(groupDetailInfoDTO); + } + + @Override + public ResponseEntity updateGroupCriteria(UUID id, GroupDetailInfoDTO dto) { + if (null == dto.getSpecificationJson() || dto.getSpecificationJson().length() == 0) { + throw new MdmdsException("Vehicle query criteria must be filled in", HttpStatus.LOCKED); + } + //dto里必须有id + VehicleGroup vehicleGroup = vehicleGroupRepository.findOneByIdAndIsDeleted(dto.getId(), 0); + if (null == vehicleGroup) { + throw new MdmdsException("Vehicle group does not exist", HttpStatus.NOT_FOUND); + } + // 分组关联车辆查询条件和标签(每个分组可以设置"事故车","G50高速"等标签) + GroupSpecification groupSpecification = vehicleGroup.getGroupSpecification(); + if (groupSpecification != null && groupSpecification.isContainSpec()) { + throw new MdmdsException("Vehicle group has been created", HttpStatus.LOCKED); + } + // 获取查询条件的车辆VID + List vidList; + try { + StringBuilder conditionSb = new StringBuilder(); + JSONObject conditionJSONObject = JSON.parseObject(dto.getSpecificationJson()); + JSONArray conditionJSONArray = conditionJSONObject.getJSONArray("and"); + for(int index = 0; index < conditionJSONArray.size(); index++){ + JSONObject itemJSONObject = conditionJSONArray.getJSONObject(index); + Set keySet = itemJSONObject.keySet(); + for(String key : keySet) { + conditionSb.append("(key").append("=").append("\"").append(key).append("\"").append(" and ") + .append(RES_VEHICLE_VALUE).append("=").append("\"").append(itemJSONObject.getString(key)).append("\")").append(" and "); + } + } + String condition = conditionSb.substring(0, conditionSb.length() - 5); + Object result = linkDTService.getVehicleIdByCondition(condition); + Vehicle vehicle = JSON.parseObject(result.toString(), Vehicle.class); + vidList = vehicle.getVehicleList(); + } catch (IOException | NoSuchAlgorithmException | KeyManagementException | ExecutionException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.CONFLICT); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.CONFLICT); + } + if (vidList.isEmpty()) { + throw new MdmdsException("Vehicle grouping condition does not have a VID", HttpStatus.CONFLICT); + } + vehicleGroup.setMold(1);// 分组创建关联VID(按车辆字段条件查询获取VID) + vehicleGroup.setStatus(ItemStatus.RUN); + // 分组关联车辆查询条件和标签(每个分组可以设置"事故车","G50高速"等标签) + groupSpecification = vehicleGroup.getGroupSpecification(); + if (groupSpecification == null) { + groupSpecification = new GroupSpecification(); + } + groupSpecification.setSpecificationJson(dto.getSpecificationJson()); + if (null != dto.getTags() && !dto.getTags().isEmpty()) { + groupSpecification.setTags(dto.getTags().stream().distinct().collect(Collectors.joining(";"))); + } else { + groupSpecification.setTags(""); + } + groupSpecRepository.save(groupSpecification); + vehicleGroup.setGroupSpecification(groupSpecification); + // 分组关联车辆 + groupService.updateGroupVehicleByCriteria(vidList, vehicleGroup, dto); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity updateGroupVin(UUID id, GroupParamsDTO dto) { + VehicleGroup vehicleGroup = vehicleGroupRepository.findOneByIdAndIsDeleted(id, 0); + if (null == vehicleGroup) { + throw new MdmdsException("Vehicle group does not exist", HttpStatus.NOT_FOUND); + } + // 分组创建中 + vehicleGroup.setMold(2);// 分组创建关联VID(按车辆VIN查询获取VID) + vehicleGroup.setStatus(ItemStatus.RUN); + GroupSpecification groupSpecification = vehicleGroup.getGroupSpecification(); + if (groupSpecification == null) { + groupSpecification = new GroupSpecification(); + } + if (null != dto.getTags() && !dto.getTags().isEmpty()) { + groupSpecification.setTags(dto.getTags().stream().collect(Collectors.joining(";"))); + } else { + groupSpecification.setTags(""); + } + groupSpecRepository.save(groupSpecification); + vehicleGroup.setGroupSpecification(groupSpecification); + vehicleGroupRepository.save(vehicleGroup); + // 异步执行:分组关联车辆 + groupService.updateGroupVehicleByVIN(vehicleGroup, dto); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity updateGroupConfiguration(UUID groupId, UUID dccId) { + groupService.updateGroupConfiguration(groupId, dccId); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity unbindGroupConfiguration(UUID groupId) { + groupService.unbindGroupConfiguration(groupId); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getVehicleIds(UUID id, GroupDetailInfoDTO groupDetailInfoDTO) { + groupService.getVehicleIds(id, groupDetailInfoDTO); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity> getAllVIDs(UUID id, GroupParamsDTO dto) { + List vehicleIds = groupService.getAllVIDs(id, dto); + return ResponseEntity.ok(vehicleIds); + } + + @Override + public ResponseEntity> getVehicleInfos(GroupVehicleDTO groupVehicleDTO) { + int pageNo = groupVehicleDTO.getPageNo(); + int pageSize = groupVehicleDTO.getPageSize(); + UUID groupId = groupVehicleDTO.getId(); + return ResponseEntity.ok(groupService.pageableVehicleInfo(PageRequest.of(pageNo - 1, pageSize), groupId)); + } + + @Override + public ResponseEntity> getVehicleViews(UUID id, GroupParamsDTO dto) { + return ResponseEntity.ok(groupService.getVehicleViews(id, dto)); + } + + @Override + public ResponseEntity createNewTicket(UUID id, TicketParamsDTO dto) { + + String ticketName = dto.getTicketName(); + List vehicleInfoDTOS = dto.getVehicles(); + ticketService.batchVehicleInsertToTicket(ticketName, vehicleInfoDTOS); + return ResponseEntity.ok().build(); + } + + @Resource + private AttributeService attributeService; + @Override + public ResponseEntity> getAllAttrValueMap() { + return ResponseEntity.ok(attributeService.getAllAttrValueMap()); + } + @Override + public ResponseEntity> getAllAttrs() { + List allAttrs = attributeService.getAllAttrs(); + return ResponseEntity.of(Optional.ofNullable(allAttrs)); + } + + @Resource + private PolicyService policyService; + @Override + public ResponseEntity getPolicyInfo(UUID id) { + PolicyBriefInfoDTO policyBriefInfoDTO = policyService.getPolicyInfo(id); + return ResponseEntity.ok(policyBriefInfoDTO); + } + + @Override + public ResponseEntity> getPolicyViews(PolicyParamsDTO dto) { + List policyBriefInfoDTOS = policyService.getPolicyViews(dto); + return ResponseEntity.ok(policyBriefInfoDTOS); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/PermissionMgmtController.java b/src/main/java/com/volkswagen/mdmds/controller/PermissionMgmtController.java new file mode 100644 index 0000000..ee2af29 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/PermissionMgmtController.java @@ -0,0 +1,291 @@ +package com.volkswagen.mdmds.controller; + +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.JwtAuthConverterProperties; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.controller.api.PermissionApi; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.param.RoleCreateParam; +import com.volkswagen.mdmds.model.param.UserStatusParam; +import com.volkswagen.mdmds.model.vo.RoleResourceTreeVo; +import com.volkswagen.mdmds.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; +import java.time.Instant; +import java.util.*; + +import static com.volkswagen.mdmds.config.JwtAuthenticationFilter.*; + + +@RestController +public class PermissionMgmtController implements PermissionApi { + + private final JwtAuthConverterProperties properties; + + @Resource + private UserService userService; + + public PermissionMgmtController(JwtAuthConverterProperties properties) { + this.properties = properties; + } + + /** + * 解析Token获取用户信息(用户基本信息、角色信息),同步更新关联用户信息 + * @param principal + * @return + */ + @Override + public ResponseEntity initUser(Principal principal) { + JwtAuthenticationToken token = (JwtAuthenticationToken) principal; + Jwt jwt = (Jwt) token.getPrincipal(); + Map claims = jwt.getClaims() ; + String userName = (String) claims.get(properties.getPrincipalAttribute()); + String email = (String) claims.get("email"); + + List roles = new ArrayList<>(); + if(jwt.hasClaim("resource_access")) { + // TSystem + initRolesInTSystem(jwt, roles); + } else { + // IDP + initRolesInIDP(jwt, roles); + } + + Collection collect = token.getAuthorities(); + List innerRoles = new ArrayList<>(); + for(GrantedAuthority item : collect) { + if(item.getAuthority().contains("ROLE_")) { + innerRoles.add(item.getAuthority().replace("ROLE_", "")); + } + } + + UserInfoDTO userInfoDTO = new UserInfoDTO(); + userInfoDTO.setUserName(userName); + userInfoDTO.setEmail(email); + + List roleInfoDTOList = roles.stream().map(roleName -> { + RoleInfoDTO roleInfoDTO = new RoleInfoDTO(); + roleInfoDTO.setRoleName(roleName); + return roleInfoDTO; + }).toList(); + userInfoDTO.setRoleList(roleInfoDTOList); + + userInfoDTO = userService.initInfo(userInfoDTO); + + List> resource = new ArrayList<>(); + for(String roleInnerName : innerRoles) { + Map resourceObj = new HashMap<>(); + resourceObj.put("resname", CommonField.INNER_MENU.get(roleInnerName)); + resource.add(resourceObj); + } + userInfoDTO.setResources(resource); + + return ResponseEntity.ok(userInfoDTO); + } + + public ResponseEntity logout(HttpServletRequest request,Principal principal) { + JwtAuthenticationToken token = (JwtAuthenticationToken) principal; + Jwt jwt = (Jwt) token.getPrincipal(); + Map claims =jwt.getClaims() ; + String userName = (String) claims.get(properties.getPrincipalAttribute()); + String deviceId = request.getHeader(properties.getUniqueAttribute()); + if (userSessionMap.containsKey(userName) && userSessionMap.get(userName).getDeviceId().equals(deviceId)) { + userSessionMap.remove(userName); + } + Instant expiresAt = (Instant) claims.get("exp"); + blackTokenMap.put(jwt.getTokenValue(),expiresAt); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", HttpStatus.OK.value()); + jsonObject.put("message","logout success"); + return ResponseEntity.ok(jsonObject); + } + + public ResponseEntity invalidToken(JSONObject token) { +// JwtAuthenticationToken token = (JwtAuthenticationToken) principal; +// Jwt jwt = (Jwt) token.getPrincipal(); +// Map claims =jwt.getClaims() ; +// Instant expiresAt = (Instant) claims.get("exp"); +// blackTokenMap.put(jwt.getTokenValue(),expiresAt); + blackTokenMap.put(token.getString("token"), Instant.now().plusSeconds(60 * 60L)); + return ResponseEntity.ok(new ResponseDTO(HttpStatus.OK,"token invalid success")); + } + + public ResponseEntity sameUserOnline(HttpServletRequest request,Principal principal) { + JwtAuthenticationToken token = (JwtAuthenticationToken) principal; + Jwt jwt = (Jwt) token.getPrincipal(); + Map claims =jwt.getClaims() ; + String userName = (String) claims.get(properties.getPrincipalAttribute()); + String deviceId = request.getHeader(properties.getUniqueAttribute()); + JSONObject jsonObject = new JSONObject(); + if (userSessionMap.containsKey(userName) && !userSessionMap.get(userName).getDeviceId().equals(deviceId)) { + jsonObject.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value()); + jsonObject.put("sameUserOnline",true); + jsonObject.put("message","The same user is online. Procedure"); + } else { + jsonObject.put("code", HttpStatus.OK.value()); + jsonObject.put("sameUserOnline",false); + jsonObject.put("message","No user is online. Procedure"); + } + return ResponseEntity.ok(jsonObject); + } + + public ResponseEntity forceLogin(HttpServletRequest request,Principal principal) { + JwtAuthenticationToken token = (JwtAuthenticationToken) principal; + Jwt jwt = (Jwt) token.getPrincipal(); + Map claims =jwt.getClaims() ; + String userName = (String) claims.get(properties.getPrincipalAttribute()); + String deviceId = request.getHeader(properties.getUniqueAttribute()); + Instant expiresAt = (Instant) claims.get("exp"); + userSessionMap.put(userName, new UserSessionDTO(userName,deviceId,expiresAt)); + return ResponseEntity.ok(new ResponseDTO(HttpStatus.OK,"force login success")); + } + + private void initRolesInTSystem(Jwt jwt, List roles) { + Map resourceAccess = jwt.getClaim("resource_access"); + if(resourceAccess != null && resourceAccess.containsKey(properties.getResourceId())) { + Map resource = (Map) resourceAccess.get(properties.getResourceId()); + List resourceRoles = (List) resource.get(CommonField.RES_ROLES); + if(!resourceRoles.isEmpty()) { + roles.addAll(resourceRoles); + } + } + } + private void initRolesInIDP(Jwt jwt, List roles) { + Map realmAccess = jwt.getClaim("realm_access"); + if(null != realmAccess && realmAccess.containsKey(CommonField.RES_ROLES)) { + List realmRoles = (List) realmAccess.get(CommonField.RES_ROLES); + if (realmRoles != null) { + roles.addAll(realmRoles); + } + } + } + + /** + * 查询用户列表 + * @param pageNo + * @param pageSize + * @return + */ + @Override + public ResponseEntity> getUserInfos(int pageNo, int pageSize) { + Page userInfoDTOS = userService.pageableUserInfos(PageRequest.of(pageNo - 1, pageSize)); + return ResponseEntity.ok(userInfoDTOS); + } + + /** + * 更新用户状态 + * @param id + * @param param + * @return + */ + @Override + public ResponseEntity alterUserStatus(UUID id, UserStatusParam param) { + userService.alterUserStatus(id, param); + return ResponseEntity.ok().build(); + } + + /** + * 查询系统角色列表 + * @param pageNo + * @param pageSize + * @return + */ + @Override + public ResponseEntity> getRoleInfos(int pageNo, int pageSize) { + Page roleInfoDTOS = userService.pageableRoleInfos(PageRequest.of(pageNo - 1, pageSize)); + return ResponseEntity.ok(roleInfoDTOS); + } + + /** + * 删除角色 + * @param id + * @return + */ + @Override + public ResponseEntity deleteRoleById(UUID id) { + userService.deleteRoleById(id); + return ResponseEntity.ok().build(); + } + + /** + * 查询系统资源列表 + * @param pageNo + * @param pageSize + * @return + */ + @Override + public ResponseEntity> getResourceInfos(int pageNo, int pageSize) { + Page resourceInfoDTOS = userService.pageableResourceInfos(PageRequest.of(pageNo - 1, pageSize)); + return ResponseEntity.ok(resourceInfoDTOS); + } + + @Override + public ResponseEntity>> getResourceViews() { + List> resourceViews = userService.getAllResourceView(); + List> resourceViewsTarget = new ArrayList<>(); + for (Map map : resourceViews) { + Map mapNew = new HashMap<>(); + mapNew.put("roleId", map.get("roleId")); + mapNew.put("roleName", map.get("roleName")); + mapNew.put("resId", map.get("resId")); + mapNew.put("resName", map.get("resName")); + mapNew.put("resUrl", map.get("resUrl")); + resourceViewsTarget.add(mapNew); + } + return ResponseEntity.ok(resourceViewsTarget); + } + + /** + * 角色下拉选项 + * @return + */ + @Override + public ResponseEntity getRoleItem() { + List roleInfoDTOS = userService.getRoleItem(); + return ResponseEntity.ok(roleInfoDTOS); + } + + /** + * 资源下拉选项 + * @return + */ + @Override + public ResponseEntity getResourceItem() { + List dicResourceDTOS = userService.getResourceItem(); + return ResponseEntity.ok(dicResourceDTOS); + } + + @Override + public ResponseEntity getTreeItem() { + List roleResourceTreeVos = userService.getTreeItem(); + return ResponseEntity.ok(roleResourceTreeVos); + } + + /** + * 分配角色权限 + * @param dto + * @return + */ + @Override + public ResponseEntity addResourceInfos(RoleResourceDetailDTO dto) { + userService.setRoleResource(dto); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity addRole(RoleCreateParam dto) { + userService.addRole(dto); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/PolicyMgmtController.java b/src/main/java/com/volkswagen/mdmds/controller/PolicyMgmtController.java new file mode 100644 index 0000000..b8bb7e2 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/PolicyMgmtController.java @@ -0,0 +1,117 @@ +package com.volkswagen.mdmds.controller; + +import com.volkswagen.mdmds.controller.api.PolicyApi; +import com.volkswagen.mdmds.model.dto.PolicyBriefInfoDTO; +import com.volkswagen.mdmds.model.dto.PolicyParamsDTO; +import com.volkswagen.mdmds.model.entity.DicVehicleAttrAdapter; +import com.volkswagen.mdmds.model.param.PolicyCreateParam; +import com.volkswagen.mdmds.model.param.PolicyDeleteParam; +import com.volkswagen.mdmds.model.param.PolicyParam; +import com.volkswagen.mdmds.model.param.PolicySearchParam; +import com.volkswagen.mdmds.repos.DicVehicleAttrAdapterRepository; +import com.volkswagen.mdmds.service.LinkHWService; +import com.volkswagen.mdmds.service.PolicyService; +import jakarta.annotation.Resource; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/28 + */ +@RestController +public class PolicyMgmtController implements PolicyApi { + + private final PolicyService policyService; + private final DicVehicleAttrAdapterRepository dicVehicleAttrAdapterRepository; + + + @Resource + private LinkHWService linkHWService; + + public PolicyMgmtController(PolicyService policyService, DicVehicleAttrAdapterRepository dicVehicleAttrAdapterRepository) { + this.policyService = policyService; + this.dicVehicleAttrAdapterRepository = dicVehicleAttrAdapterRepository; + } + +// @Override +// public ResponseEntity receiveDcc(DccDTO dto) { +// DataCollectionConfig dataCollectionConfig = policyService.upsertOneDCC(dto); +// if (null != dataCollectionConfig.getId()) { +// return ResponseEntity.ok(dataCollectionConfig); +// } else { +// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); +// } +// } + +// @Override +// public ResponseEntity> getPolicyInfos(int pageNo, int pageSize) { +// Page policyBriefInfoDTOS = policyService.pageableBriefPolicy(PageRequest.of(pageNo-1, pageSize)); +// return ResponseEntity.ok(policyBriefInfoDTOS); +// } + + @Override + public ResponseEntity> getPolicySearch(PolicySearchParam param) { + Page policyBriefInfoDTOS = policyService.searchPolicyPage(param); + return ResponseEntity.ok(policyBriefInfoDTOS); + } + + @Override + public ResponseEntity deleteConfiguration(@RequestBody PolicyDeleteParam param) { + policyService.deleteConfigurationByIds(param.getIdList()); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getPolicyInfo(UUID id) { + PolicyBriefInfoDTO policyBriefInfoDTO = policyService.getPolicyInfo(id); + return ResponseEntity.ok(policyBriefInfoDTO); + } + + @Override + public ResponseEntity> getPolicyViews(PolicyParamsDTO dto) { + List policyBriefInfoDTOS = policyService.getPolicyViews(dto); + return ResponseEntity.ok(policyBriefInfoDTOS); + } + + @Override + public ResponseEntity getPolicyEventList(PolicyParam param) { + // 映射表查询adsVersion值 + DicVehicleAttrAdapter dicVehicleAttrAdapter = dicVehicleAttrAdapterRepository.findByAdapterMapping(param.getAdsVersion()); + String adsVersion = null; + if (dicVehicleAttrAdapter != null && StringUtils.hasText(dicVehicleAttrAdapter.getAdapterKey())) { + adsVersion = dicVehicleAttrAdapter.getAdapterKey(); + } + return ResponseEntity.ok(linkHWService.getEventListByAdsVersion(adsVersion)); + } + +// @Override +// public ResponseEntity getPolicyConfiguration(@Parameter(description = "查询条件") @RequestBody PolicyParam param) { +// return ResponseEntity.ok(linkHWService.getPolicyByAdsVersionAndEvent(param)); +// } + +// @Override +// public ResponseEntity save(PolicySaveParam param) { +// policyService.save(param); +// return ResponseEntity.ok().build(); +// } + + @Override + public ResponseEntity create(@RequestBody PolicyCreateParam param) { + DicVehicleAttrAdapter dicVehicleAttrAdapter = dicVehicleAttrAdapterRepository.findByAdapterMapping(param.getAdsVersion()); + String adsVersion = null; + if (dicVehicleAttrAdapter != null && StringUtils.hasText(dicVehicleAttrAdapter.getAdapterKey())) { + adsVersion = dicVehicleAttrAdapter.getAdapterKey(); + } + param.setAdsVersion(adsVersion); + policyService.create(param); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/TestController.java b/src/main/java/com/volkswagen/mdmds/controller/TestController.java new file mode 100644 index 0000000..5289df7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/TestController.java @@ -0,0 +1,71 @@ +package com.volkswagen.mdmds.controller; + +import com.volkswagen.mdmds.model.dto.RoleInfoDTO; +import com.volkswagen.mdmds.model.dto.UserInfoDTO; +import com.volkswagen.mdmds.service.AuditService; +import com.volkswagen.mdmds.service.UserService; +import jakarta.annotation.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; +import java.util.List; +import java.util.Map; + +/** + * @author Shuo Ding + * @since 2023/3/6 + */ +@RestController +@RequestMapping("/test") +public class TestController { + + @Resource + private UserService userService; + @Resource + private AuditService auditService; + + @GetMapping("/anonymous") + public ResponseEntity getAnonymous(Principal principal) { + int abc = auditService.countByCondition("ABC"); + if(abc>=0){ + return ResponseEntity.ok("Hello Anonymous 0803"); + }else{ + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + + } + + @GetMapping("/admin") + public ResponseEntity getAdmin(Principal principal) { + return ResponseEntity.ok("Hello Admin "); + } + + @GetMapping("/user") + public ResponseEntity getUser(Principal principal) { + JwtAuthenticationToken token = (JwtAuthenticationToken) principal; + String userName = (String) token.getTokenAttributes().get("name"); + String email = (String) token.getTokenAttributes().get("email"); + Map> roleObject = (Map>) token.getTokenAttributes().get("realm_access"); + List roles = roleObject.get("roles"); + + UserInfoDTO userInfoDTO = new UserInfoDTO(); + userInfoDTO.setUserName(userName); + userInfoDTO.setEmail(email); + + List roleInfoDTOList = roles.stream().map(x -> { + RoleInfoDTO roleInfoDTO = new RoleInfoDTO(); + roleInfoDTO.setRoleName(x); + return roleInfoDTO; + }).toList(); + userInfoDTO.setRoleList(roleInfoDTOList); + + userService.initInfo(userInfoDTO); + + return ResponseEntity.ok("Hello User \nUser Name : " + userName + "\nUser Email : " + email + "\nRoles : " + roles.toString()); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/TicketMgmtController.java b/src/main/java/com/volkswagen/mdmds/controller/TicketMgmtController.java new file mode 100644 index 0000000..a8ca571 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/TicketMgmtController.java @@ -0,0 +1,147 @@ +package com.volkswagen.mdmds.controller; + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.controller.api.TicketApi; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.Ticket; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.param.TicketUpdateParam; +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.TicketVo; +import com.volkswagen.mdmds.repos.TicketRepository; +import com.volkswagen.mdmds.service.TicketService; +import jakarta.annotation.Resource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@RestController +public class TicketMgmtController implements TicketApi { + + @Resource + private TicketRepository ticketRepository; + + private final TicketService ticketService; + + public TicketMgmtController(TicketService ticketService) { + this.ticketService = ticketService; + } + + @Override + public ResponseEntity createTicket(TicketBriefInfoDTO dto) { + dto.setStatus(ItemStatus.NONE); + Ticket ticket = ticketService.createTicket(dto); + if (ticket.getId() != null) { + return ResponseEntity.ok(ticket); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity addVinToTicket(UUID id, String vin) { + Ticket ticket = ticketService.addVinToTicket(id, vin); + if (ticket.getId() != null) { + return ResponseEntity.ok(ticket); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity> getPageableTicket(TicketParam param) { + Page ticketVoPage = ticketService.pageableTicket(param.getPageNo(), param.getPageSize(), param); + return ResponseEntity.ok(ticketVoPage); + } + + @Override + public ResponseEntity updateTicketDescription(UUID id, TicketUpdateParam dto) { + Ticket ticket = ticketService.updateTicketDescription(id, dto); + if (ticket.getId() != null) { + return ResponseEntity.ok(ticket); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity updateGroupVin(UUID id, TicketParamsDTO dto) { + List vinList = dto.getVinList(); + for(String vin : vinList) { + if(vin.length() != 17) { + throw new MdmdsException("VIN code error", HttpStatus.NOT_FOUND); + } + } + Ticket ticket = ticketRepository.findOneByIdAndIsDeleted(id, 0); + if (null == ticket) { + throw new MdmdsException("The ticket does not exist", HttpStatus.NOT_FOUND); + } + if (!ticket.getStatus().equals(ItemStatus.NONE)) { + throw new MdmdsException("The ticket status is incorrect", HttpStatus.LOCKED); + } + ticket.setStatus(ItemStatus.RUN); + ticketRepository.save(ticket); + // 后台异步执行:工单关联VIN + ticketService.updateGroupVinAndInfo(ticket, dto); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity changeTicketStatus(UUID id, TicketBriefInfoDTO dto) { + Ticket ticket = ticketService.changeTicketStatus(id, dto); + if (ticket.getId() != null) { + return ResponseEntity.ok(ticket); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity deleteTicket(UUID id) { + List idList = new ArrayList<>(); + idList.add(id); + ticketService.deleteTicketByIds(idList); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity deleteTicketByIds(TicketParamsDTO dto) { + ticketService.deleteTicketByIds(dto.getIdList()); + return ResponseEntity.ok().build(); + } + + @Override + public ResponseEntity getTicketDetail(UUID id) { + TicketDetailDTO ticketDetailDTO = ticketService.getTicketDetail(id); + if (ticketDetailDTO.getId() != null) { + return ResponseEntity.ok(ticketDetailDTO); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + @Override + public ResponseEntity> getVehicleViews(UUID id, TicketParamsDTO dto) { + return ResponseEntity.ok(ticketService.getVehicleViews(id, dto)); + } + + @Override + public ResponseEntity> getVehicleInfos(TicketVehicleDTO dto) { + int pageNo = dto.getPageNo(); + int pageSize = dto.getPageSize(); + UUID ticketId = dto.getId(); + return ResponseEntity.ok(ticketService.pageableVehicleInfo(PageRequest.of(pageNo - 1, pageSize), ticketId)); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/VehicleController.java b/src/main/java/com/volkswagen/mdmds/controller/VehicleController.java new file mode 100644 index 0000000..43b17ab --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/VehicleController.java @@ -0,0 +1,55 @@ +package com.volkswagen.mdmds.controller; + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.controller.api.VehicleApi; +import com.volkswagen.mdmds.model.dto.VehicleParamsDTO; +import com.volkswagen.mdmds.model.dto.VehicleReturnDTO; +import com.volkswagen.mdmds.service.VehicleService; +import com.volkswagen.mdmds.utils.AntStrUtil; +import jakarta.annotation.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@RestController +public class VehicleController implements VehicleApi { + + @Resource + private VehicleService vehicleService; + + @Override + public ResponseEntity> getVidByVin(VehicleParamsDTO dto) { + List vinList = dto.getVinList(); + for(String vin : vinList) { + if(!AntStrUtil.isVIN(vin)) { + throw new MdmdsException(CommonField.VIN_ERROR, HttpStatus.NOT_FOUND); + } + } + List list = vehicleService.getVidList(dto); + return ResponseEntity.ok(list); + } + + @Override + public ResponseEntity> getVinByVID(VehicleParamsDTO dto) { + List list = vehicleService.getVinList(dto); + return ResponseEntity.ok(list); + } + + @Override + public ResponseEntity> getVehicleInfoByVid(VehicleParamsDTO dto) { + List list = vehicleService.getVehicleInfoList(dto); + return ResponseEntity.ok(list); + } + + @Override + public ResponseEntity getVehicleFieldValue(String name) { + String result = vehicleService.getVehicleFieldValuesByName(name); + return ResponseEntity.ok(result); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/AttributeApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/AttributeApi.java new file mode 100644 index 0000000..85de5be --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/AttributeApi.java @@ -0,0 +1,138 @@ +package com.volkswagen.mdmds.controller.api; + +import com.volkswagen.mdmds.model.dto.AttrWithValuesDTO; +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.dto.UploadDataDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.UUID; + +/** + * 车辆属性API + * + * @author Shuo Ding + * @since 2023/2/20 + */ +@Tag(name = AttributeApi.Constants.API_NAME,description = "车辆属性API") +public interface AttributeApi { + + @PostMapping(value = Constants.BASE_PATH) + @Operation(summary = "添加一个新的车辆属性", description = "根据车辆属性名称,映射关系,状态新建一个车辆属性,创建属性默认状态是ENABLE") + default ResponseEntity addAttribute(@Parameter(description = "车辆属性",required = true)@Valid @RequestBody AttributeDTO attributeDTO) { + return null; + } + + @GetMapping(value = Constants.BASE_PATH + "/all") + @Operation(summary = "查看已有的车辆属性") + default ResponseEntity> getAllAttrs() { + return null; + } + + @PostMapping(value = Constants.BASE_PATH + "/views") + @Operation(summary = "根据条件查询车辆属性字段", + description = "车辆属性字段不多(同DT接口同步校验),不使用分页(status为ENABLE或DISABLE,为null时查询所有数据)") + default ResponseEntity> getAttrViews(@Parameter(description = "车辆属性",required = true) @RequestBody AttributeDTO attributeDTO) { + return null; + } + + @PutMapping(value = Constants.BASE_PATH + "/{id}" + "/status") + @Operation(summary = "更新车辆属性状态", description = "根据车辆属性id更新状态(ENABLE,DISABLE)") + default ResponseEntity changeAttributeStatus( + @PathVariable(value = "id") @Parameter(description = "属性的唯一ID") UUID id, + @Parameter(description = "只需要传status,只有两个选项(ENABLE,DISABLE)") @RequestBody AttributeDTO dto) { + return null; + } + + @DeleteMapping(value = Constants.BASE_PATH + "/delete" + "/{id}") + @Operation(summary = "删除车辆属性字段", description = "通过车辆属性字段ID删除") + default ResponseEntity deleteAttributeById(@PathVariable(value = "id") @Parameter(description = "车型属性的唯一ID") UUID id) { + return null; + } + + @DeleteMapping(value = Constants.BASE_PATH + "/clear") + @Operation(summary = "一键删除所有车辆属性") + default ResponseEntity clearTable() { + return null; + } + + @GetMapping(value = Constants.BASE_PATH + "/verification") + @Operation(summary = "校验数据车辆属性字段与DT的属性字段", description = "比对数据库与DT的属性字段名称,更新结果") + default ResponseEntity verification() { + return null; + } + + @GetMapping(value = Constants.BASE_PATH + "/values") + @Operation(summary = "同步车辆属性字段的值", description = "根据数据库车辆属性字段名称同步DT接口返回的值") + default ResponseEntity getAttrValue() { + return null; + } + + @PutMapping(value = Constants.BASE_PATH + "/{id}") + @Operation(summary = "更新或创建指定ID的车辆属性") + default ResponseEntity updateVehicleAttr( + @PathVariable(value = "id") @Parameter(description = "属性ID",required = true,example = "1234") UUID id, + @RequestBody @Parameter(description = "车辆属性信息",required = true)AttributeDTO attributeDTO) { + return null; + } + + @PostMapping(value = Constants.BASE_PATH + "/checkedAttr") + @Operation(summary = "校验车辆属性字段名称是否与DT一致", description = "根据车辆属性字段名称(attrName)校验是否在DT存在") + default ResponseEntity verificationAttrName(@Parameter(description = "车辆属性",required = true)@Valid @RequestBody AttributeDTO attributeDTO) { + return null; + } + + @PutMapping(value = Constants.BASE_PATH + "/kv") + @Operation(summary = "获取车辆属性的键值对",description = "系统会定时聚合可能存在的属性-值组合,用于界面的下拉选项") + default ResponseEntity> getAllAttrValueMap() { + return null; + } + + @PostMapping(value = Constants.BASE_PATH + "/excel/upload") + @Operation(summary = "上传车辆字段", description = "车辆字段作为查询车辆VID的条件,创建分组时需要根据车辆字段查询VID") + default ResponseEntity uploadExcel(@RequestParam MultipartFile file) { + return null; + } + + @PostMapping(value = Constants.BASE_PATH + "/excel/upload/check") + @Operation(summary = "校验上传的车辆字段", description = "车辆字段作为查询车辆VID的条件,创建分组时需要根据车辆字段查询VID") + default ResponseEntity uploadExcelCheck(@RequestParam MultipartFile file) { + return null; + } + @PostMapping(value = Constants.BASE_PATH + "/excel/upload/data") + @Operation(summary = "上传校验后的车辆字段", description = "车辆字段作为查询车辆VID的条件,创建分组时需要根据车辆字段查询VID") + default ResponseEntity uploadExcelData(@Valid @RequestBody UploadDataDTO uploadDataDTO) { + return null; + } + + @GetMapping(value = Constants.BASE_PATH + "/excel/downloadTemplate") + @Operation(summary = "下载车辆字段模板", description = "车辆字段作为查询车辆VID的条件,创建分组时需要根据车辆字段查询VID") + default ResponseEntity downloadExcelTemplate(HttpServletResponse response) { + return null; + } + + @GetMapping(value = Constants.BASE_PATH + "/update/vehicle") + @Operation(summary = "同步DT的车辆字段更新入库", description = "") + default ResponseEntity updateVehicleKeyAndValue(HttpServletResponse response) { + return null; + } + + @SuppressWarnings("WeakerAccess") + final class Constants { + public static final String API_NAME = "attribute"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/GroupApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/GroupApi.java new file mode 100644 index 0000000..9e4eb08 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/GroupApi.java @@ -0,0 +1,174 @@ +package com.volkswagen.mdmds.controller.api; + +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.param.GroupCreateParam; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +/** + * 车辆分组管理API + * + * @author Shuo Ding + * @since 2023/2/21 + */ +@Tag(name = GroupApi.Constants.API_NAME, description = "车辆分组管理API") +@Validated +public interface GroupApi { + @PostMapping(value = GroupApi.Constants.BASE_PATH) + @Operation(summary = "创建车辆分组", description = "只需要输入组名,具体内容使用更新接口,只需要填写组名,其他都可不填") + default ResponseEntity createGroup( + @Parameter(description = "车辆分组名称,只需要填写组名,其他都可不填") + @RequestBody @Valid GroupCreateParam groupBriefInfoDTO) { + return null; + } + + @DeleteMapping(value = GroupApi.Constants.BASE_PATH + "/{id}") + @Operation(summary = "删除分组", description = "根据ID删除分组") + default ResponseEntity deleteGroupById( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/delete") + @Operation(summary = "删除分组-批量", description = "根据批量ID删除分组") + default ResponseEntity deletedGroupByIds( + @RequestBody(required = true) @Parameter(description = "输入批量分组ID('idList')") @Valid GroupParamsDTO dto) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/page") + @Operation(summary = "查询所有车辆分组的简要信息", description = "根据分页条件,展示车辆分组基础信息") + default ResponseEntity> getPageableGroup(@RequestBody @Valid VehicleGroupParam param) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/{id}") + @Operation(summary = "查询车辆分组的详细信息", description = "主要包含动态的分组信息和分组元数据,车辆信息不在这个接口返回") + default ResponseEntity getGroupDetailInfo( + @PathVariable(value = "id") @Parameter(description = "车辆分组唯一ID", required = true) UUID id) { + return null; + } + + @PutMapping(value = GroupApi.Constants.BASE_PATH + "/{id}") + @Operation(summary = "更新车辆分组的条件", description = "分组条件是动态的,需要用打平的json字符串传输") + default ResponseEntity updateGroupCriteria( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @RequestBody(required = true) @Parameter(description = "车辆分组是动态的,界面可以下拉选择,也可以输入") @Valid GroupDetailInfoDTO dto) { + return null; + } + + @PutMapping(value = GroupApi.Constants.BASE_PATH + "/vin/{id}") + @Operation(summary = "更新车辆分组的VIN", description = "分组关联多辆车,车通过vin关联。入参需要tags, vinList, version") + default ResponseEntity updateGroupVin( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @RequestBody(required = true) GroupParamsDTO dto) { + return null; + } + + @GetMapping(value = GroupApi.Constants.BASE_PATH + "/configuration") + @Operation(summary = "更新车辆分组的配置", description = "关联车辆分组ID和配置ID") + default ResponseEntity updateGroupConfiguration( + @RequestParam(name = "groupId") @Parameter(description = "车辆分组ID", required = true) UUID groupId, + @RequestParam(name = "dccId") @Parameter(description = "配置项ID", required = false) UUID dccId) { + return null; + } + + @GetMapping(value = GroupApi.Constants.BASE_PATH + "/configuration/unbind") + @Operation(summary = "解除车辆分组的配置", description = "解除车辆分组ID和配置ID") + default ResponseEntity unbindGroupConfiguration( + @RequestParam(name = "groupId") @Parameter(description = "车辆分组ID", required = true) UUID groupId) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/vehicle/getVIDs/{id}") + @Operation(summary = "X查询车辆ID更新分组关联的车辆ID", description = "根据条件从DT接口获取VIDs") + default ResponseEntity getVehicleIds( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @Parameter(description = "车辆分组条件,只需要填写分组条件,其他都可不填") + @RequestBody GroupDetailInfoDTO groupDetailInfoDTO) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/vehicle/getAllVIDs/{id}") + @Operation(summary = "根据车辆字段条件查询车辆VID", description = "根据车辆字段条件从DT接口获取VIDs用于前端展示,入参Body部分需要specificationJson") + default ResponseEntity> getAllVIDs( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @Parameter(description = "车辆查询条件,只需要填写'specificationJson'", example = "{\"and\":[{\"color\":\"blue\"},{\"brand_name\":\"Audi\"}]}") + @RequestBody GroupParamsDTO dto) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/vehicle/getInfos") + @Operation(summary = "根据分组查询关联的车辆列表", description = "根据条件创建的分组通过VID获取车辆信息,根据VIN创建的分组通过VIN获取车辆信息。需要入参id为分组id,其他字段不需要") + default ResponseEntity> getVehicleInfos(@RequestBody GroupVehicleDTO groupVehicleDTO) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/vehicle/views/{id}") + @Operation(summary = "根据车辆VID查询车辆信息", description = "根据车辆VID查询车辆信息,需要入参vidList为多个车辆VID") + default ResponseEntity> getVehicleViews( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @Parameter(description = "车辆信息查询,只需要填写'vidList'") + @RequestBody GroupParamsDTO dto) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/ticket/create/{id}") + @Operation(summary = "根据分组车辆创建工单") + default ResponseEntity createNewTicket( + @PathVariable @Parameter(description = "车辆分组唯一ID", required = true) UUID id, + @Parameter(description = "批量车辆关联创建的工单") + @RequestBody TicketParamsDTO dto) { + return null; + } + + @GetMapping(value = GroupApi.Constants.BASE_PATH + "/attribute/all") + @Operation(summary = "查看已有的车辆属性") + default ResponseEntity> getAllAttrs() { + return null; + } + + @PutMapping(value = GroupApi.Constants.BASE_PATH + "/attribute/kv") + @Operation(summary = "获取车辆属性的键值对",description = "系统会定时聚合可能存在的属性-值组合,用于界面的下拉选项") + default ResponseEntity> getAllAttrValueMap() { + return null; + } + + @GetMapping(value = GroupApi.Constants.BASE_PATH + "/policy/detail/{id}") + @Operation(summary = "查询配置信息", description = "根据配置ID查询配置详细信息") + default ResponseEntity getPolicyInfo( + @PathVariable @Parameter(description = "配置唯一ID", required = true) UUID id) { + return null; + } + + @PostMapping(value = GroupApi.Constants.BASE_PATH + "/policy/view") + @Operation(summary = "根据版本查询所有配置", description = "查询结果用于根据车辆版本关联可选的配置版本") + default ResponseEntity> getPolicyViews(@Parameter(description = "查询条件") @RequestBody PolicyParamsDTO dto) { + return null; + } + + @SuppressWarnings("WeakerAccess") + final class Constants { + public static final String API_NAME = "group"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/PermissionApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/PermissionApi.java new file mode 100644 index 0000000..da388a8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/PermissionApi.java @@ -0,0 +1,151 @@ +package com.volkswagen.mdmds.controller.api; + +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.param.RoleCreateParam; +import com.volkswagen.mdmds.model.param.UserStatusParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.security.Principal; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Tag(name = PermissionApi.Constants.API_NAME, description = "权限管理API") +@Validated +public interface PermissionApi { + + final class Constants { + public static final String API_NAME = "permission"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String USER_PATH = BASE_PATH + "/user"; + public static final String ROLE_PATH = BASE_PATH + "/role"; + public static final String RESOURCE_PATH = BASE_PATH + "/resource"; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + + @GetMapping(value = PermissionApi.Constants.USER_PATH + "/login") + @Operation(summary = "初始化用户信息", description = "解析Token获取用户关联的角色权限信息") + default ResponseEntity initUser( + @Parameter(description = "解析token获取用户信息,token必填") Principal principal) { + return null; + } + + @GetMapping(value = PermissionApi.Constants.USER_PATH + "/sameUserOnline") + @Operation(summary = "当前已有相同用户在线", description = "当前已有相同用户在线") + default ResponseEntity sameUserOnline(HttpServletRequest request,@Parameter(description = "解析token获取用户信息,token必填") Principal principal) { + return null; + } + + @GetMapping(value = PermissionApi.Constants.USER_PATH + "/logout") + @Operation(summary = "退出登录", description = "退出登录") + default ResponseEntity logout(HttpServletRequest request,@Parameter(description = "解析token获取用户信息,token必填") Principal principal) { + return null; + } + + @PostMapping(value = PermissionApi.Constants.USER_PATH + "/invalidToken") + @Operation(summary = "token失效", description = "token失效") + default ResponseEntity invalidToken(@RequestBody JSONObject token) { + return null; + } + + @GetMapping(value = PermissionApi.Constants.USER_PATH + "/forceLogin") + @Operation(summary = "强制登录", description = "强制登录") + default ResponseEntity forceLogin(HttpServletRequest request, @Parameter(description = "解析token获取用户信息,token必填") Principal principal) { + return null; + } + + + @GetMapping(value = PermissionApi.Constants.USER_PATH + "/list") + @Operation(summary = "分页查询所有用户信息",description = "根据分页条件,展示用户的基础信息") + default ResponseEntity> getUserInfos( + @RequestParam(name = "pageNo",defaultValue = "1") @Parameter(description = "页码",required = true) int pageNo, + @RequestParam(name = "pageSize",defaultValue = "10") @Parameter(description = "每页显示的数量",required = false)int pageSize) { + return null; + } + + @PutMapping(value = PermissionApi.Constants.USER_PATH + "/{id}" + "/status") + @Operation(summary = "禁用用户", description = "根据用户id更新状态(ENABLE,DISABLE)") + default ResponseEntity alterUserStatus( + @PathVariable(value = "id") @Parameter(description = "属性的唯一ID") UUID id, + @Parameter(description = "只需要传status,只有两个选项(ENABLE,DISABLE)") @RequestBody UserStatusParam param) { + return null; + } + + @GetMapping(value = PermissionApi.Constants.ROLE_PATH + "/list") + @Operation(summary = "分页查询所有角色信息",description = "根据分页条件,展示角色的基础信息") + default ResponseEntity> getRoleInfos( + @RequestParam(name = "pageNo",defaultValue = "1") @Parameter(description = "页码",required = true) int pageNo, + @RequestParam(name = "pageSize",defaultValue = "10") @Parameter(description = "每页显示的数量",required = false)int pageSize) { + return null; + } + + @DeleteMapping(value = PermissionApi.Constants.ROLE_PATH + "/{id}") + @Operation(summary = "删除角色",description = "根据ID删除角色") + default ResponseEntity deleteRoleById(@PathVariable @Parameter(description = "角色唯一ID", required = true) UUID id) { + return null; + } + + @GetMapping(value = PermissionApi.Constants.RESOURCE_PATH + "/list") + @Operation(summary = "查询所有资源信息",description = "根据分页条件,展示资源的基础信息") + default ResponseEntity> getResourceInfos( + @RequestParam(name = "pageNo",defaultValue = "1") @Parameter(description = "页码",required = true) int pageNo, + @RequestParam(name = "pageSize",defaultValue = "10") @Parameter(description = "每页显示的数量",required = false)int pageSize) { + return null; + } + @GetMapping(value = PermissionApi.Constants.RESOURCE_PATH + "/view") + @Operation(summary = "查询所有资源信息",description = "展示资源的基础信息") + default ResponseEntity>> getResourceViews() { + return null; + } + + @GetMapping(value = PermissionApi.Constants.ROLE_PATH + "/item") + @Operation(summary = "查询所有角色ID及名称",description = "查询角色选项") + default ResponseEntity getRoleItem() { + + return null; + } + + @GetMapping(value = PermissionApi.Constants.RESOURCE_PATH + "/item") + @Operation(summary = "查询所有资源ID及名称",description = "查询资源选项") + default ResponseEntity getResourceItem() { + + return null; + } + + @GetMapping(value = PermissionApi.Constants.ROLE_PATH + "/tree") + @Operation(summary = "查询角色菜单结构", description = "查询角色菜单结构选项") + default ResponseEntity getTreeItem() { + return null; + } + + + + + + + @PostMapping(value = PermissionApi.Constants.RESOURCE_PATH + "/add") + @Operation(summary = "创建角色资源", description = "添加资源并分配给角色") + default ResponseEntity addResourceInfos(@Parameter(description = "分配角色权限") @RequestBody @Valid RoleResourceDetailDTO dto) { + return null; + } + + @PostMapping(value = Constants.ROLE_PATH + "/add") + @Operation(summary = "创建角色", description = "创建角色") + default ResponseEntity addRole(@Parameter(description = "创建角色") @RequestBody @Valid RoleCreateParam dto) { + return null; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/PolicyApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/PolicyApi.java new file mode 100644 index 0000000..ae2fc1d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/PolicyApi.java @@ -0,0 +1,111 @@ +package com.volkswagen.mdmds.controller.api; + +import com.volkswagen.mdmds.model.dto.DccDTO; +import com.volkswagen.mdmds.model.dto.PolicyBriefInfoDTO; +import com.volkswagen.mdmds.model.dto.PolicyParamsDTO; +import com.volkswagen.mdmds.model.param.*; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/28 + */ +@Tag(name = PolicyApi.Constants.API_NAME,description = "车辆分组管理API") +public interface PolicyApi { + @SuppressWarnings("WeakerAccess") + final class Constants { + public static final String API_NAME = "policy"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + + +// @GetMapping(value = PolicyApi.Constants.BASE_PATH) +// @Operation(summary = "查询所有策略的简要信息",description = "根据分页条件,展示策略的基础信息") +// default ResponseEntity> getPolicyInfos( +// @RequestParam(name = "pageNo",defaultValue = "1") @Parameter(description = "页码") int pageNo, +// @RequestParam(name = "pageSize",defaultValue = "10") @Parameter(description = "每页显示的数量",required = false) +// @Positive(message = "每页数量必须是正数") int pageSize) { +// return null; +// } + + @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/search") + @Operation(summary = "查询所有策略的简要信息",description = "根据分页条件,展示策略的基础信息") + default ResponseEntity> getPolicySearch( + @RequestBody PolicySearchParam param) { + return null; + } + + @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/delete") + @Operation(summary = "删除配置", description = "根据配置ID删除") + default ResponseEntity deleteConfiguration(@RequestBody PolicyDeleteParam param) { + return null; + } + +// @PostMapping(value = PolicyApi.Constants.BASE_PATH) +// @Operation(summary = "接收配置信息",description = "接收来自于EHRM的配置信息,只能接收EHRM的调用!") +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200",description = "成功"), +// @ApiResponse(responseCode = "500",description = "未知错误"), +// @ApiResponse(responseCode = "409",description = "配置项已经存在") +// }) +// @SecurityRequirement(name = "Bearer Authentication") +// default ResponseEntity receiveDcc(@Parameter(description = "数据收集策略") @RequestBody DccDTO dto) { +// return null; +// } + + @GetMapping(value = PolicyApi.Constants.BASE_PATH + "/detail/{id}") + @Operation(summary = "查询配置信息", description = "根据配置ID查询配置详细信息") + default ResponseEntity getPolicyInfo( + @PathVariable @Parameter(description = "配置唯一ID", required = true) UUID id) { + return null; + } + + @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/view") + @Operation(summary = "根据版本查询所有配置", description = "查询结果用于根据车辆版本关联可选的配置版本") + default ResponseEntity> getPolicyViews(@Parameter(description = "查询条件") @RequestBody PolicyParamsDTO dto) { + return null; + } + + @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/event/list") + @Operation(summary = "根据版本查询EventList", description = "") + default ResponseEntity getPolicyEventList(@Parameter(description = "查询条件") @RequestBody PolicyParam param) { + return null; + } + +// @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/configuration") +// @Operation(summary = "根据版本和EventList查询Configuration", description = "") +// default ResponseEntity getPolicyConfiguration(@Parameter(description = "查询条件") @RequestBody PolicyParam param) { +// return null; +// } + +// @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/save") +// @Operation(summary = "创建Configuration", description = "") +// default ResponseEntity save(@RequestBody PolicySaveParam param) { +// return null; +// } + + @PostMapping(value = PolicyApi.Constants.BASE_PATH + "/create") + @Operation(summary = "创建Configuration", description = "") + default ResponseEntity create(@RequestBody @Valid PolicyCreateParam param) { + return null; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/TicketApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/TicketApi.java new file mode 100644 index 0000000..5c37cea --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/TicketApi.java @@ -0,0 +1,127 @@ +package com.volkswagen.mdmds.controller.api; + +import com.volkswagen.mdmds.model.dto.TicketBriefInfoDTO; +import com.volkswagen.mdmds.model.dto.TicketDetailDTO; +import com.volkswagen.mdmds.model.dto.TicketParamsDTO; +import com.volkswagen.mdmds.model.dto.TicketVehicleDTO; +import com.volkswagen.mdmds.model.dto.TicketVehicleResultDTO; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.param.TicketUpdateParam; +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.TicketVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; +import java.util.UUID; + +/** + * 车辆异常工单管理API + * + * @author Shuo Ding + * @since 2023/2/21 + */ +@Tag(name = TicketApi.Constants.API_NAME,description = "车辆分组管理API") +public interface TicketApi { + @SuppressWarnings("WeakerAccess") + final class Constants { + public static final String API_NAME = "ticket"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + + @PostMapping(value = TicketApi.Constants.BASE_PATH) + @Operation(summary = "创建新工单",description = "根据名称生成新的工单,具体信息使用更新接口,工单名称必填,其他无用") + default ResponseEntity createTicket(@Parameter(description = "工单名称必填,其他无用") @Valid @RequestBody TicketBriefInfoDTO dto) { + return null; + } + + @PostMapping(value = TicketApi.Constants.BASE_PATH + "/page") + @Operation(summary = "查询所有异常工单的简要信息",description = "根据分页条件,展示异常工单的基础信息") + default ResponseEntity> getPageableTicket(@RequestBody @Valid TicketParam param) { + return null; + } + + @PutMapping(value = TicketApi.Constants.BASE_PATH + "/des" + "/{id}") + @Operation(summary = "更新工单描述",description = "只需要传描述字段,其余无用") + default ResponseEntity updateTicketDescription( + @PathVariable(value = "id") @Parameter(description = "工单的唯一ID") UUID id, + @Parameter(description = "工单的描述") @RequestBody @Valid TicketUpdateParam dto) { + return null; + } + + @PutMapping(value = TicketApi.Constants.BASE_PATH + "/vin/{id}") + @Operation(summary = "工单添加异常车辆信息(批量)", description = "工单关联多个车辆VIN,入参只传vinList") + default ResponseEntity updateGroupVin( + @PathVariable @Parameter(description = "工单唯一ID", required = true) UUID id, + @RequestBody(required = true) TicketParamsDTO dto) { + return null; + } + + + @PutMapping(value = TicketApi.Constants.BASE_PATH + "/vin" + "/{id}" + "/{vin}") + @Operation(summary = "X工单添加异常车辆信息(停用)", + description = "只需要传vin,系统收到vin后会去db或digital twin要车辆的信息,然后存到本地,和ticket进行关联") + default ResponseEntity addVinToTicket( + @PathVariable(value = "id") @Parameter(description = "工单的唯一ID") UUID id, + @PathVariable(value = "vin")String vin) { + + return null; + } + + @PutMapping(value = TicketApi.Constants.BASE_PATH + "/{id}" + "/status") + @Operation(summary = "改变工单状态",description = "只需要传status,只有两个选项HOLD,DONE。其他选项会报错") + default ResponseEntity changeTicketStatus(@PathVariable(value = "id") @Parameter(description = "工单的唯一ID") UUID id, + @Parameter(description = "状态") @RequestBody TicketBriefInfoDTO dto) { + return null; + } + + @DeleteMapping(value = TicketApi.Constants.BASE_PATH + "/delete" + "/{id}") + @Operation(summary = "删除工单", description = "根据工单ID删除") + default ResponseEntity deleteTicket(@PathVariable(value = "id") @Parameter(description = "工单的唯一ID") UUID id) { + return null; + } + + @PostMapping(value = TicketApi.Constants.BASE_PATH + "/delete") + @Operation(summary = "删除工单-批量", description = "根据工单ID删除") + default ResponseEntity deleteTicketByIds(@RequestBody(required = true) @Parameter(description = "输入批量工单ID('idList')") @Valid TicketParamsDTO dto) { + return null; + } + + @GetMapping(value = TicketApi.Constants.BASE_PATH + "/detail" + "/{id}") + @Operation(summary = "查询工单详细信息", description = "根据id获取工单关联的车辆信息") + default ResponseEntity getTicketDetail(@PathVariable(value = "id") @Parameter(description = "工单的唯一ID") UUID id) { + return null; + } + + @PostMapping(value = TicketApi.Constants.BASE_PATH + "/vehicle/views/{id}") + @Operation(summary = "根据车辆VID查询车辆信息", description = "根据车辆VID查询车辆信息,需要入参vidList为多个车辆VID") + default ResponseEntity> getVehicleViews( + @PathVariable @Parameter(description = "工单唯一ID", required = true) UUID id, + @Parameter(description = "车辆信息查询,只需要填写'vidList'") + @RequestBody TicketParamsDTO dto) { + return null; + } + + @PostMapping(value = TicketApi.Constants.BASE_PATH + "/vehicle/getInfos") + @Operation(summary = "根据工单查询关联的车辆列表", + description = "工单ID查询关联的VID,再根据VID查询车辆信息。需要入参id为工单id,其他字段不需要") + default ResponseEntity> getVehicleInfos(@RequestBody TicketVehicleDTO ticketVehicleDTO) { + return null; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/controller/api/VehicleApi.java b/src/main/java/com/volkswagen/mdmds/controller/api/VehicleApi.java new file mode 100644 index 0000000..b2165b4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/controller/api/VehicleApi.java @@ -0,0 +1,55 @@ +package com.volkswagen.mdmds.controller.api; + +import com.volkswagen.mdmds.model.dto.VehicleParamsDTO; +import com.volkswagen.mdmds.model.dto.VehicleReturnDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +@Tag(name = VehicleApi.Constants.API_NAME, description = "车辆管理API") +public interface VehicleApi { + + @SuppressWarnings("WeakerAccess") + final class Constants { + public static final String API_NAME = "vehicle"; + public static final String BASE_PATH = "/mdmds" + "/v1/" + API_NAME; + public static final String VERSION = "1.0.0"; + + private Constants() { + super(); + } + } + + @PostMapping(value = VehicleApi.Constants.BASE_PATH + "/getVIDs") + @Operation(summary = "根据车辆VIN查询VID", + description = "根据车辆VIN查询车辆VID:传参vinList;返回statusCode代表VWAC接口错误码(正常为null),返回message代表错误信息") + default ResponseEntity> getVidByVin(@RequestBody(required = true) VehicleParamsDTO dto) { + return null; + } + + @PostMapping(value = VehicleApi.Constants.BASE_PATH + "/getVINs") + @Operation(summary = "根据车辆VID查询VIN", + description = "根据车辆VIN查询车辆VID:传参vidList;返回statusCode代表VWAC接口错误码(正常为null),返回message代表错误信息") + default ResponseEntity> getVinByVID(@RequestBody(required = true) VehicleParamsDTO dto) { + return null; + } + + @PostMapping(value = VehicleApi.Constants.BASE_PATH + "/getVehicleInfo") + @Operation(summary = "根据车辆VID查询车辆信息", + description = "根据车辆VID查询车辆信息(处理DT接口返回的Json数据):传参vidList") + default ResponseEntity> getVehicleInfoByVid(@RequestBody(required = true) VehicleParamsDTO dto) { + return null; + } + + @GetMapping(value = VehicleApi.Constants.BASE_PATH + "/field/values/{name}") + @Operation(summary = "获取车辆字段的数据", description = "例如:根据ads_version获取车辆的ADS Version") + default ResponseEntity getVehicleFieldValue(@PathVariable(value = "name") String name) { + return null; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/AttrWithValuesDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/AttrWithValuesDTO.java new file mode 100644 index 0000000..c6b805e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/AttrWithValuesDTO.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.model.dto; + +import com.alibaba.fastjson.JSONArray; +import lombok.Data; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@Data +public class AttrWithValuesDTO { + private String attrName; + private JSONArray values; + + private String mappingName; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/AttributeDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/AttributeDTO.java new file mode 100644 index 0000000..9d19e8e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/AttributeDTO.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.model.dto; + +import com.volkswagen.mdmds.model.entity.ItemStatus; +import jakarta.validation.constraints.NotEmpty; +import lombok.*; + +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@Data +public class AttributeDTO{ + private UUID id; + + @NotEmpty(message = "车辆属性名称是必填项") + private String attrName; + private String mappingName; + private ItemStatus status; + + private String remark; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/AuditDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/AuditDTO.java new file mode 100644 index 0000000..9a19e3d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/AuditDTO.java @@ -0,0 +1,29 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.Date; +import java.util.UUID; + +@Data +public class AuditDTO { + + private UUID id; + + private String log; + + private String reqIP; + + private String reqURI; + + private String reqMethod; + + private String reqMethodName; + + private String reqParams; + + private Date startTime; + + private Date endTime; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/DccDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/DccDTO.java new file mode 100644 index 0000000..b54e078 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/DccDTO.java @@ -0,0 +1,50 @@ +package com.volkswagen.mdmds.model.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/2/28 + *

+ * Data Collection Configuration + *

+ * { + * "comments":"policy1“ + * "subscription": "policy1", + * "adsVersion": "ADSV 1.0.0-A0000001.B001", + * "configuration": "c2hhMjU2IG9mIGNvbmZpZ3VyYXRpb24ncyBiYXNlNjQgc3RyaW5n", + * "sha256": "71568f9eb4ee7d3711c3f1d0e31c8b6b9b7086bec70e1487e279367bf243fe8e", + * "events":[{ + * "eventId": "10000", + * "eventName": "Matual handler", + * "eventDesc": "Matual handler", + * "eventType": "trigger", + * "eventScope": [-15, 5] + * },{ + * "eventId": "99999", + * "eventName": "Vehicle Status", + * "eventDesc": "Vehicle Status", + * "eventType": "periodic", + * "eventScope": null + * }] + * } + */ +@Getter +@Setter +public class DccDTO { + private String comments; + @NotEmpty(message = "subscription是必填项") + private String subscription; + @NotEmpty(message = "adsVersion是必填项") + private String adsVersion; + @NotEmpty(message = "configuration是必填项") + private String configuration; + private String sha256; + private List events; + + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/DicResourceDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/DicResourceDTO.java new file mode 100644 index 0000000..ffaafec --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/DicResourceDTO.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class DicResourceDTO { + + private UUID resId; + + private String resName; + + private String resUrl; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/EventDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/EventDTO.java new file mode 100644 index 0000000..245d771 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/EventDTO.java @@ -0,0 +1,20 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/2/28 + */ +@Getter +@Setter +public class EventDTO { + private String eventId; + private String eventName; + private String eventDesc; + private String eventType; + private List> eventScope; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupBriefInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupBriefInfoDTO.java new file mode 100644 index 0000000..c656329 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupBriefInfoDTO.java @@ -0,0 +1,39 @@ +package com.volkswagen.mdmds.model.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@Setter +@Getter +@NoArgsConstructor +@Builder +public class GroupBriefInfoDTO { + protected UUID id; + + @NotEmpty(message = "Group Name is required") +// @Pattern(regexp = "^[a-z0-9A-Z\u4e00-\u9fa5]+$") + private String groupName; + + private String status; + private String specificationJson; + private String tags; + private Integer mold; + + public GroupBriefInfoDTO(UUID id, String groupName, String status, String specificationJson, String tags, Integer mold) { + this.id = id; + this.groupName = groupName; + this.status = status; + this.specificationJson = specificationJson; + this.tags = tags; + this.mold = mold; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupDetailInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupDetailInfoDTO.java new file mode 100644 index 0000000..2611574 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupDetailInfoDTO.java @@ -0,0 +1,36 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@Getter +@Setter +public class GroupDetailInfoDTO { + protected UUID id; + private String groupName; + private ItemStatus status; + @NotEmpty + private String specificationJson; + private List tags; + private List vehicles; + //从EHR-M收到的数据接收策略的名字 + private String dccName; + private UUID dccId; + private String createBy; + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupParamsDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupParamsDTO.java new file mode 100644 index 0000000..93ef6a4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupParamsDTO.java @@ -0,0 +1,25 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +public class GroupParamsDTO { + + private String specificationJson; + + private List tags; + + private List vidList; + + private List vinList; + private String version; + + /** + * 分组ID + */ + private List idList; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupReturnDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupReturnDTO.java new file mode 100644 index 0000000..8d9f877 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupReturnDTO.java @@ -0,0 +1,27 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +import java.util.Date; +import java.util.UUID; + +@Data +public class GroupReturnDTO { + + protected UUID id; + private String groupName; + private ItemStatus status; + private String statusDes; + private Integer mold; + private Integer total; + + protected String createBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + protected Date creationDate; + protected String lastModifiedBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + protected Date lastModifiedDate; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleDTO.java new file mode 100644 index 0000000..270eda7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleDTO.java @@ -0,0 +1,25 @@ +package com.volkswagen.mdmds.model.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.UUID; + +@Data +public class GroupVehicleDTO { + + @NotBlank(message = "车辆分组ID不能为空") + private UUID id; + + @NotEmpty(message = "车辆字段查询条件不能为空,并且是Json字符串({\"and\":[{\"color\":\"blue\"},{\"brand_name\":\"Audi\"}]})") + private String specificationJson; + + @Min(value = 1, message = "页码必须大于1") + private int pageNo; + + @Min(value = 5, message = "每页最少显示5条数据") + private int pageSize; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleResultDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleResultDTO.java new file mode 100644 index 0000000..d13eeea --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/GroupVehicleResultDTO.java @@ -0,0 +1,12 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +@Data +public class GroupVehicleResultDTO { + + private String vid; + + private String infos; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/MappingAllFieldDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/MappingAllFieldDTO.java new file mode 100644 index 0000000..dadfd52 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/MappingAllFieldDTO.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +/** + * MappingAllFieldDTO + * + * @author Chen Li + * @since 4/11/2025 + */ +@Data +public class MappingAllFieldDTO { + + private MappingFieldDTO data; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/MappingFieldDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/MappingFieldDTO.java new file mode 100644 index 0000000..03a09b2 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/MappingFieldDTO.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +/** + * MappingFieldDTO + * + * @author Chen Li + * @since 4/11/2025 + */ +@Data +public class MappingFieldDTO { + + private String ADSVersion; + + private String MDCVersion; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBaseDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBaseDTO.java new file mode 100644 index 0000000..9c5423c --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBaseDTO.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.dto; + +import com.volkswagen.mdmds.model.param.PolicyCreateParam; +import lombok.Data; + +import java.util.List; + +@Data +public class PolicyBaseDTO { + + private String adsVersion; + private List events; + + private String sha256; + private String configuration; + + private String taskId; + private String startTime; + private String endTime; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBriefInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBriefInfoDTO.java new file mode 100644 index 0000000..09cd49b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyBriefInfoDTO.java @@ -0,0 +1,43 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.*; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/3/2 + */ +@Getter +@Setter +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +public class PolicyBriefInfoDTO { + + private UUID id; + private String adsVersion; + private String eventList; + private String dccDetail; + + private String description; + private String subscription; + + protected String createBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + protected Date creationDate; + protected String lastModifiedBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + protected Date lastModifiedDate; + + private String groupName; + + private String apiForm; + private String taskId; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date startTime; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date endTime; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/PolicyParamsDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyParamsDTO.java new file mode 100644 index 0000000..ceca8b4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/PolicyParamsDTO.java @@ -0,0 +1,10 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +@Data +public class PolicyParamsDTO { + + private String adsVersion; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/ResourceInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/ResourceInfoDTO.java new file mode 100644 index 0000000..7d76639 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/ResourceInfoDTO.java @@ -0,0 +1,17 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class ResourceInfoDTO { + + private String resName; + private String resUrl; + + private UUID roleId; + private UUID resId; + + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/ResponseDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/ResponseDTO.java new file mode 100644 index 0000000..3d54abf --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/ResponseDTO.java @@ -0,0 +1,51 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; +import org.springframework.http.HttpStatus; + +import java.util.Date; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@Getter +@Setter +public class ResponseDTO { + + @JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd hh:mm:ss") + private Date timestamp; + private int code; + private String status; + private String message; + private String stackTrace; + private Object data; + + public ResponseDTO() { + this.timestamp=new Date(); + } + + public ResponseDTO(HttpStatus httpStatus, String message) { + this(); + this.code=httpStatus.value(); + this.status=httpStatus.name(); + this.message=message; + } + + public ResponseDTO(HttpStatus httpStatus, String message, String stackTrace) { + this(httpStatus,message); + this.stackTrace=stackTrace; + } + + public ResponseDTO(HttpStatus httpStatus, String message, String stackTrace, Object data) { + this(httpStatus, message, stackTrace); + this.data=data; + } + + public ResponseDTO(HttpStatus httpStatus,Object data) { + this(httpStatus, ""); + this.data=data; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/RoleInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/RoleInfoDTO.java new file mode 100644 index 0000000..8583beb --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/RoleInfoDTO.java @@ -0,0 +1,30 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; +import java.util.UUID; + +@Data +public class RoleInfoDTO { + + private String roleName; + + private String resName; + + private UUID id; + + private String createBy; + + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date creationDate; + + private String lastModifiedBy; + + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/RoleResourceDetailDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/RoleResourceDetailDTO.java new file mode 100644 index 0000000..40cbfba --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/RoleResourceDetailDTO.java @@ -0,0 +1,17 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.Set; +import java.util.UUID; + +@Data +public class RoleResourceDetailDTO { + + private UUID id; + + private String roleName; + + private Set resource; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/TicketBriefInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/TicketBriefInfoDTO.java new file mode 100644 index 0000000..0d40b53 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/TicketBriefInfoDTO.java @@ -0,0 +1,36 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@Getter +@Setter +public class TicketBriefInfoDTO { + + protected UUID id; + + @NotEmpty(message = "Ticket Name is required") + @Length(max = 20, message = "Character length cannot exceed 20") + private String ticketName; + + private String ticketDetail; + + private String createBy; + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + private ItemStatus status; + private String statusDes; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/TicketDetailDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/TicketDetailDTO.java new file mode 100644 index 0000000..dab36c6 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/TicketDetailDTO.java @@ -0,0 +1,31 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.VehicleInfo; +import lombok.Data; + +import java.util.*; + +@Data +public class TicketDetailDTO { + + protected UUID id; + private String ticketName; + private String ticketDetail; + private ItemStatus status; + + private String createBy; + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date creationDate; + private String lastModifiedBy; + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + + private Set vehicleInfoes = new LinkedHashSet<>(); + + private List vehicles; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/TicketParamsDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/TicketParamsDTO.java new file mode 100644 index 0000000..b7c280d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/TicketParamsDTO.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +public class TicketParamsDTO { + + private String ticketName; + + private List vehicles; + + private List idList; + + private List vidList; + + private List vinList; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleDTO.java new file mode 100644 index 0000000..acfc2e3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleDTO.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.util.UUID; + +@Data +public class TicketVehicleDTO { + + @NotBlank(message = "工单ID不能为空") + private UUID id; + + @Min(value = 1, message = "页码必须大于1") + private int pageNo; + + @Min(value = 5, message = "每页最少显示5条数据") + private int pageSize; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleResultDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleResultDTO.java new file mode 100644 index 0000000..ff3d598 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/TicketVehicleResultDTO.java @@ -0,0 +1,12 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +@Data +public class TicketVehicleResultDTO { + + private String vid; + + private String infos; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/UploadDataDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/UploadDataDTO.java new file mode 100644 index 0000000..2152c78 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/UploadDataDTO.java @@ -0,0 +1,22 @@ +package com.volkswagen.mdmds.model.dto; + +import com.volkswagen.mdmds.model.param.DataSourceAdapterParam; +import com.volkswagen.mdmds.model.param.DataSourceParam; +import lombok.Data; + +import java.util.List; + +/** + * 上传参数 + * + * @author Chen Li + * @since 4/23/2025 + */ +@Data +public class UploadDataDTO { + + private List list; + + private List adapterlist; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/UserInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/UserInfoDTO.java new file mode 100644 index 0000000..75da459 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/UserInfoDTO.java @@ -0,0 +1,34 @@ +package com.volkswagen.mdmds.model.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Data +public class UserInfoDTO { + + private String userName; + + private String email; + + private List roleList; + + private String roles; + + private List realRoles; + + private List> resources; + + private UUID id; + + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + + private ItemStatus status; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/UserSessionDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/UserSessionDTO.java new file mode 100644 index 0000000..2a7b30b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/UserSessionDTO.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.dto; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.Instant; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserSessionDTO { + + private String username; + + private String deviceId; + + private Instant exp; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/VehicleInfoDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleInfoDTO.java new file mode 100644 index 0000000..dee3b57 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleInfoDTO.java @@ -0,0 +1,14 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +@Data +public class VehicleInfoDTO { + + private String vin; + + private String vid; + + private String infos; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/VehicleParamsDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleParamsDTO.java new file mode 100644 index 0000000..8b1c5d5 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleParamsDTO.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Builder +@Data +public class VehicleParamsDTO { + + private List vinList; + + private List vidList; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/dto/VehicleReturnDTO.java b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleReturnDTO.java new file mode 100644 index 0000000..e896462 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/dto/VehicleReturnDTO.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.model.dto; + +import lombok.Data; + +@Data +public class VehicleReturnDTO { + + private String vin; + + private String vid; + + private String infos; + private String result; + + private String statusCode; + private String message; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/AuditLog.java b/src/main/java/com/volkswagen/mdmds/model/entity/AuditLog.java new file mode 100644 index 0000000..1078d11 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/AuditLog.java @@ -0,0 +1,41 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@Entity +@Table(name = "audit_log") +public class AuditLog extends BaseEntity { + + @Column(name = "log", columnDefinition = "text") + private String log; + + @Column(name = "req_ip", columnDefinition = "Varchar(50)") + private String reqIP; + + @Column(name = "req_uri", columnDefinition = "Varchar(100)") + private String reqURI; + + @Column(name = "req_method", columnDefinition = "Varchar(50)") + private String reqMethod; + + @Column(name = "req_method_name", columnDefinition = "Varchar(50)") + private String reqMethodName; + + @Column(name = "req_params", columnDefinition = "text") + private String reqParams; + + @Column(name = "start_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date startTime; + + @Column(name = "end_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date endTime; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/BaseEntity.java b/src/main/java/com/volkswagen/mdmds/model/entity/BaseEntity.java new file mode 100644 index 0000000..f3360f5 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/BaseEntity.java @@ -0,0 +1,44 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.util.Date; +import java.util.UUID; + +@Getter +@Setter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + protected UUID id; + + @CreatedBy + protected U createBy; + + //带时区的时间戳 + @Temporal(TemporalType.TIMESTAMP) + @CreatedDate + @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE") + protected Date creationDate; + + @LastModifiedBy + protected U lastModifiedBy; + + @LastModifiedDate + @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE") + protected Date lastModifiedDate; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/DataCollectionConfig.java b/src/main/java/com/volkswagen/mdmds/model/entity/DataCollectionConfig.java new file mode 100644 index 0000000..bfe46eb --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/DataCollectionConfig.java @@ -0,0 +1,48 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@Entity +@Table(name = "data_collection_config") +public class DataCollectionConfig extends BaseEntity { + + private String adsVersion; + private String eventList; + + @Column(columnDefinition = "text") + private String dccDetail; + private String uniqueMd5; + private String contentMd5; + private String description; + private String subscription; + + /** + * 删除状态:0-正常 1-删除 + */ + @Column(name = "is_deleted", columnDefinition = "int not null default 0") + private Integer isDeleted; + + /** + * 接口类型:HW-API1,HW-API2 + */ + @Column(name = "api_form", columnDefinition = "Varchar(50)") + private String apiForm; + + @Column(name = "task_id", columnDefinition = "Varchar(50)") + private String taskId; + + @Column(name = "start_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date startTime; + + @Column(name = "end_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date endTime; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/DicAttrValueEnum.java b/src/main/java/com/volkswagen/mdmds/model/entity/DicAttrValueEnum.java new file mode 100644 index 0000000..9940d5f --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/DicAttrValueEnum.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "dic_attr_value_eumn") +public class DicAttrValueEnum { + @Id + private String attrName; + + @Column(name = "attr_val", columnDefinition = "text") + private String attrVal; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/DicResource.java b/src/main/java/com/volkswagen/mdmds/model/entity/DicResource.java new file mode 100644 index 0000000..b996642 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/DicResource.java @@ -0,0 +1,38 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import org.springframework.data.annotation.CreatedBy; + +import java.util.Date; +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "dic_resource") +public class DicResource { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + protected UUID id; + private String resName; + private String resUrl; + @CreatedBy + private String createBy; + + @Column(name = "creation_date", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date creationDate; + + private String lastModifiedBy; + + @Column(name = "last_modified_date", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date lastModifiedDate; + + + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttr.java b/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttr.java new file mode 100644 index 0000000..9620a39 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttr.java @@ -0,0 +1,22 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "dic_vehicle_attr") +public class DicVehicleAttr extends BaseEntity { + private String attrName; + private String mappingName; + + @Enumerated(EnumType.STRING) + @Column(length=16) + private ItemStatus status; + + @Column(name = "remark", columnDefinition = "text") + private String remark; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttrAdapter.java b/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttrAdapter.java new file mode 100644 index 0000000..b13d146 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/DicVehicleAttrAdapter.java @@ -0,0 +1,22 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "dic_vehicle_attr_adapter") +public class DicVehicleAttrAdapter extends BaseEntity { + + private String attrName; + + @Column(unique = true) + private String adapterMapping; + + private String adapterKey; + + private String adapterValue; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/GroupConfiguration.java b/src/main/java/com/volkswagen/mdmds/model/entity/GroupConfiguration.java new file mode 100644 index 0000000..539a727 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/GroupConfiguration.java @@ -0,0 +1,36 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "group_configuration") +public class GroupConfiguration extends BaseEntity { + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "group_id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID groupId; + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "dcc_id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID dccId; + + @PrePersist + public void prePersist() { + if (this.groupId == null) { + this.groupId = UUID.randomUUID(); + } + if (this.dccId == null) { + this.dccId = UUID.randomUUID(); + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/GroupDccRecord.java b/src/main/java/com/volkswagen/mdmds/model/entity/GroupDccRecord.java new file mode 100644 index 0000000..e879483 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/GroupDccRecord.java @@ -0,0 +1,38 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "group_dcc_record") +public class GroupDccRecord extends BaseEntity { + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "group_id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID groupId; + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "dcc_id") + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID dccId; + + @PrePersist + public void prePersist() { + if (this.groupId == null) { + this.groupId = UUID.randomUUID(); + } + if (this.dccId == null) { + this.dccId = UUID.randomUUID(); + } + } + + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/GroupSpecification.java b/src/main/java/com/volkswagen/mdmds/model/entity/GroupSpecification.java new file mode 100644 index 0000000..4e3c018 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/GroupSpecification.java @@ -0,0 +1,31 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +@Getter +@Setter +@Entity +@Table(name = "group_specification") +public class GroupSpecification extends BaseEntity { + + @Column(columnDefinition = "text") + private String specificationJson; + + //标签,使用';'分割 + @Column(columnDefinition = "text") + private String tags; + + /** + * 判断是否已经设置过分组条件或者是标签 + * + * @return + */ + public Boolean isContainSpec() { + return !(StringUtils.isEmpty(this.specificationJson) && StringUtils.isEmpty(this.tags)); + } +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/GroupVehicle.java b/src/main/java/com/volkswagen/mdmds/model/entity/GroupVehicle.java new file mode 100644 index 0000000..e3fd9d2 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/GroupVehicle.java @@ -0,0 +1,46 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "group_vehicle") +public class GroupVehicle extends BaseEntity { + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "group_id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID groupId; + + @Column(name = "vid") + private String vid; + + @Column(name = "vin") + private String vin; + + @Column(name = "infos", columnDefinition = "json") + private String infos; + + @Column(name = "result", columnDefinition = "json") + private String result; + + @Column(name = "status_code") + private String statusCode; + @Column(name = "message", columnDefinition="text") + private String message; + + @PrePersist + public void prePersist() { + if (this.groupId == null) { + this.groupId = UUID.randomUUID(); + } + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/ItemStatus.java b/src/main/java/com/volkswagen/mdmds/model/entity/ItemStatus.java new file mode 100644 index 0000000..449f51b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/ItemStatus.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.model.entity; + +/** + * 数据条目的状态 + * + * @author Shuo Ding + * @since 2023/2/20 + */ +public enum ItemStatus { + ENABLE,DISABLE,NONE,RUN,HOLD,DONE,ALL +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/RoleInfo.java b/src/main/java/com/volkswagen/mdmds/model/entity/RoleInfo.java new file mode 100644 index 0000000..d3e8b51 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/RoleInfo.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.util.LinkedHashSet; +import java.util.Set; + +@Getter +@Setter +@Entity +@Table(name = "role_info") +public class RoleInfo extends BaseEntity { + private String roleName; + + private String innerRole; + + @ManyToMany + @JoinTable(name = "role_info_dic_resources", + joinColumns = @JoinColumn(name = "role_info_id"), + inverseJoinColumns = @JoinColumn(name = "dic_resources_id")) + private Set dicResources = new LinkedHashSet<>(); +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/Ticket.java b/src/main/java/com/volkswagen/mdmds/model/entity/Ticket.java new file mode 100644 index 0000000..2dff7d9 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/Ticket.java @@ -0,0 +1,35 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "ticket") +public class Ticket extends BaseEntity { + + private String ticketName; + private String ticketDetail; + + @Enumerated(EnumType.STRING) + @Column(length = 16) + private ItemStatus status; + + /** + * 删除状态:0-正常 1-删除 + */ + @Column(name = "is_deleted", columnDefinition = "int not null default 0") + private Integer isDeleted; + + /** + * Ticket关联的车数量 + */ + @Column(name = "total", columnDefinition = "int NOT NULL DEFAULT 0 ") + private Integer total; + + @Column(name = "vines", columnDefinition = "TEXT") + private String vines; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/TicketVehicle.java b/src/main/java/com/volkswagen/mdmds/model/entity/TicketVehicle.java new file mode 100644 index 0000000..8ff4d40 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/TicketVehicle.java @@ -0,0 +1,45 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "ticket_vehicle") +public class TicketVehicle extends BaseEntity { + +// @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "ticket_id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + private UUID ticketId; + + @Column(name = "vid") + private String vid; + + @Column(name = "vin") + private String vin; + + @Column(name = "infos", columnDefinition = "json") + private String infos; + + @Column(name = "result", columnDefinition = "json") + private String result; + + @Column(name = "status_code") + private String statusCode; + @Column(name = "message", columnDefinition="text") + private String message; + + @PrePersist + public void prePersist() { + if (this.ticketId == null) { + this.ticketId = UUID.randomUUID(); + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/UserInfo.java b/src/main/java/com/volkswagen/mdmds/model/entity/UserInfo.java new file mode 100644 index 0000000..72e7b75 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/UserInfo.java @@ -0,0 +1,56 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import org.springframework.data.annotation.CreatedBy; + +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; + +@Getter +@Setter +@Entity +@Table(name = "user_info") +public class UserInfo { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Column(name = "id", nullable = false) + @JdbcTypeCode(value = SqlTypes.CHAR) + protected UUID id; + + @ManyToMany + @JoinTable(name = "user_info_role_infoes", + joinColumns = @JoinColumn(name = "user_info_id"), + inverseJoinColumns = @JoinColumn(name = "role_infoes_id")) + private Set roleInfoes = new LinkedHashSet<>(); + + @Column(name = "user_name", columnDefinition = "Varchar(50)") + private String userName; + + @Column(name = "email", columnDefinition = "Varchar(50)") + private String email; + + @Column(name = "roles", columnDefinition = "text") + private String roles; + + @CreatedBy + private String createBy; + + @Column(name = "creation_date", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date creationDate; + + private String lastModifiedBy; + + @Column(name = "last_modified_date", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private Date lastModifiedDate; + + @Enumerated(EnumType.STRING) + @Column(name = "status", columnDefinition = "varchar(16) NOT NULL DEFAULT 'ENABLE'") + private ItemStatus status; + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/VehicleGroup.java b/src/main/java/com/volkswagen/mdmds/model/entity/VehicleGroup.java new file mode 100644 index 0000000..beefb8c --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/VehicleGroup.java @@ -0,0 +1,37 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "vehicle_group") +@Data +public class VehicleGroup extends BaseEntity { + + private String groupName; + private ItemStatus status; + + @OneToOne(orphanRemoval = true) + @JoinColumn(name = "group_specification_id") + private GroupSpecification groupSpecification; + + /** + * '删除状态:0-正常 1-删除' + */ + @Column(name = "is_deleted", columnDefinition = "int NOT NULL DEFAULT 0 ") + private Integer isDeleted; + + /** + * '删除状态:0-分组无条件 1-字段查询条件 2-VIN查询条件' + */ + @Column(name = "mold", columnDefinition = "int NOT NULL DEFAULT 0 ") + private Integer mold; + + /** + * Group关联的车数量 + */ + @Column(name = "total", columnDefinition = "int NOT NULL DEFAULT 0 ") + private Integer total; + + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/entity/VehicleInfo.java b/src/main/java/com/volkswagen/mdmds/model/entity/VehicleInfo.java new file mode 100644 index 0000000..a92d7f4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/entity/VehicleInfo.java @@ -0,0 +1,45 @@ +package com.volkswagen.mdmds.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.Hibernate; + +import java.util.Objects; + +@Getter +@Setter +@Entity +@Table(name = "vehicle_info") +public class VehicleInfo extends BaseEntity { + + @Column(unique = true) + private String vid; + + @Column(name = "vin") + private String vin; + + @Column(columnDefinition = "json") + private String infos; + + @Column(columnDefinition = "json") + private String result; + + @Column(name = "status_code") + private String statusCode; + @Column(columnDefinition = "json") + private String message; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + VehicleInfo that = (VehicleInfo) o; + return vin != null && Objects.equals(vin, that.vin); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeAdapterField.java b/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeAdapterField.java new file mode 100644 index 0000000..e030840 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeAdapterField.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.model.excel; + +import com.volkswagen.mdmds.utils.annotation.ExcelField; +import lombok.Data; + +@Data +public class VehicleAttributeAdapterField { + + @ExcelField(name = "Attribute Name", order = 1) + private String attrName; + + @ExcelField(name = "Key", order = 2) + private String adapterKey; + + @ExcelField(name = "Value", order = 3) + private String adapterValue; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeField.java b/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeField.java new file mode 100644 index 0000000..eab4a26 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/excel/VehicleAttributeField.java @@ -0,0 +1,15 @@ +package com.volkswagen.mdmds.model.excel; + +import com.volkswagen.mdmds.utils.annotation.ExcelField; +import lombok.Data; + +@Data +public class VehicleAttributeField { + + @ExcelField(name = "Attribute Name", order = 1) + private String attrName; + + @ExcelField(name = "Mapping Name", order = 2) + private String mappingName; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/DataSourceAdapterParam.java b/src/main/java/com/volkswagen/mdmds/model/param/DataSourceAdapterParam.java new file mode 100644 index 0000000..20e21c8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/DataSourceAdapterParam.java @@ -0,0 +1,12 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +@Data +public class DataSourceAdapterParam { + + private String attrName; + private String adapterKey; + private String adapterValue; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/DataSourceParam.java b/src/main/java/com/volkswagen/mdmds/model/param/DataSourceParam.java new file mode 100644 index 0000000..69ece88 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/DataSourceParam.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +@Data +public class DataSourceParam { + + private String attrName; + private String mappingName; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/GroupCreateParam.java b/src/main/java/com/volkswagen/mdmds/model/param/GroupCreateParam.java new file mode 100644 index 0000000..8cdeda7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/GroupCreateParam.java @@ -0,0 +1,23 @@ +package com.volkswagen.mdmds.model.param; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +@Setter +@Getter +@NoArgsConstructor +@Builder +public class GroupCreateParam { + + @NotEmpty(message = "Group Name is required") + @Length(max = 20, message = "Group Name length cannot exceed 20") + private String groupName; + + public GroupCreateParam(String groupName) { + this.groupName = groupName; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicyCreateParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicyCreateParam.java new file mode 100644 index 0000000..34e5df9 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicyCreateParam.java @@ -0,0 +1,40 @@ +package com.volkswagen.mdmds.model.param; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +@Data +public class PolicyCreateParam { + + @Length(max = 200, message = "Comments length cannot exceed 200") + private String comments; + + @NotEmpty(message = "Subscription is required") + @Length(max = 200, message = "Comments length cannot exceed 200") + private String subscription; + + @NotEmpty(message = "adsVersion is required") + private String adsVersion; + + private List events; + + @NotEmpty(message = "apiForm is required") + private String apiForm; + private String startTime; + private String endTime; + + private List timeSlot; + + @Data + public static class EventParam { + private String eventId; + private String eventName; + private String eventDesc; + private String eventType; + private List> eventScope; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicyDeleteParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicyDeleteParam.java new file mode 100644 index 0000000..6f1e5fa --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicyDeleteParam.java @@ -0,0 +1,13 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +public class PolicyDeleteParam { + + private List idList; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicyParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicyParam.java new file mode 100644 index 0000000..1394382 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicyParam.java @@ -0,0 +1,14 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +import java.util.List; + +@Data +public class PolicyParam { + + private String adsVersion; + + private List events; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicyReqParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicyReqParam.java new file mode 100644 index 0000000..8db82f0 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicyReqParam.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +import java.util.List; + +@Data +public class PolicyReqParam { + + private String adsVersion; + + private List events; + + private String taskId; + private Long startTime; + private Long endTime; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicySaveParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicySaveParam.java new file mode 100644 index 0000000..701b1e7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicySaveParam.java @@ -0,0 +1,33 @@ +package com.volkswagen.mdmds.model.param; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.util.List; + +@Data +public class PolicySaveParam { + + private String comments; + + @NotEmpty(message = "subscription是必填项") + private String subscription; + + @NotEmpty(message = "adsVersion是必填项") + private String adsVersion; + + private String configuration; + + private String sha256; + private List events; + + @Data + public static class EventParam { + private String eventId; + private String eventName; + private String eventDesc; + private String eventType; + private List> eventScope; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/PolicySearchParam.java b/src/main/java/com/volkswagen/mdmds/model/param/PolicySearchParam.java new file mode 100644 index 0000000..48cfe7d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/PolicySearchParam.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +@Data +public class PolicySearchParam { + + private Integer pageNo; + private Integer pageSize; + + private String adsVersion; + private String subscription; + + private String sortField; + private String sortOrder; + + private String apiForm; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/RoleCreateParam.java b/src/main/java/com/volkswagen/mdmds/model/param/RoleCreateParam.java new file mode 100644 index 0000000..0db80f7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/RoleCreateParam.java @@ -0,0 +1,10 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; + +@Data +public class RoleCreateParam { + + private String roleName; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/TicketParam.java b/src/main/java/com/volkswagen/mdmds/model/param/TicketParam.java new file mode 100644 index 0000000..d15da9a --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/TicketParam.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.param; + +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +@Data +public class TicketParam { + + private Integer pageNo; + private Integer pageSize; + + private String ticketName; + + private ItemStatus status; + +// private String totalMin; +// private String totalMax; + + private String vin; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/TicketUpdateParam.java b/src/main/java/com/volkswagen/mdmds/model/param/TicketUpdateParam.java new file mode 100644 index 0000000..c180b11 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/TicketUpdateParam.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.model.param; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.UUID; + +@Data +public class TicketUpdateParam { + + protected UUID id; + + @Length(max = 200, message = "Description length cannot exceed 200") + private String ticketDetail; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/UserStatusParam.java b/src/main/java/com/volkswagen/mdmds/model/param/UserStatusParam.java new file mode 100644 index 0000000..794160b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/UserStatusParam.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.model.param; + +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +@Data +public class UserStatusParam { + + private ItemStatus status; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/param/VehicleGroupParam.java b/src/main/java/com/volkswagen/mdmds/model/param/VehicleGroupParam.java new file mode 100644 index 0000000..9978f08 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/param/VehicleGroupParam.java @@ -0,0 +1,22 @@ +package com.volkswagen.mdmds.model.param; + +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +@Data +public class VehicleGroupParam { + +// @Min(value = 1, message = "页码必须大于1") + private int pageNo; +// +// @Min(value = 5, message = "每页最少显示5条数据") + private int pageSize; + + private String groupName; + + private ItemStatus status; + + private String totalMin; + private String totalMax; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/pojo/DccBriefPojo.java b/src/main/java/com/volkswagen/mdmds/model/pojo/DccBriefPojo.java new file mode 100644 index 0000000..84e77d8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/pojo/DccBriefPojo.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.pojo; + +import com.volkswagen.mdmds.model.dto.EventDTO; +import lombok.Data; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/3/7 + * + * 与DCCDTO其实是一样的,但是这个是为了剔除其中的描述属性 + */ +@Data +public class DccBriefPojo { + + private String subscription; + private String adsVersion; + private String configuration; + private List events; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/pojo/GroupVehicleInfoPojo.java b/src/main/java/com/volkswagen/mdmds/model/pojo/GroupVehicleInfoPojo.java new file mode 100644 index 0000000..6f2977a --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/pojo/GroupVehicleInfoPojo.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.pojo; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class GroupVehicleInfoPojo { + + private UUID groupId; + + private String vid; + + private String vin; + + private String infos; + + private String statusCode; + private String message; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/pojo/TicketVehicleInfoPojo.java b/src/main/java/com/volkswagen/mdmds/model/pojo/TicketVehicleInfoPojo.java new file mode 100644 index 0000000..350292f --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/pojo/TicketVehicleInfoPojo.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.model.pojo; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class TicketVehicleInfoPojo { + + private UUID ticketId; + + private String vid; + + private String vin; + + private String infos; + + private String statusCode; + private String message; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/ExcelCheckVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/ExcelCheckVo.java new file mode 100644 index 0000000..b44e4cb --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/ExcelCheckVo.java @@ -0,0 +1,32 @@ +package com.volkswagen.mdmds.model.vo; + +import com.alibaba.excel.EasyExcel; +import lombok.Data; + +import java.util.List; + +@Data +public class ExcelCheckVo { + + private String message; + private List list; + private List adapterlist; + + @Data + public static class DataSourceVo { + private String attrName; + private String mappingName; + } + + @Data + public static class DataSourceAdapterVo { + private String attrName; + private String adapterKey; + private String adapterValue; + } + + public static void main(String[] args) { +// EasyExcel.read() + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/ResourceVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/ResourceVo.java new file mode 100644 index 0000000..3218392 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/ResourceVo.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.model.vo; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class ResourceVo { + + private UUID resId; + private String resName; + private String resUrl; + + private boolean checked = Boolean.FALSE; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/RoleResourceTreeVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/RoleResourceTreeVo.java new file mode 100644 index 0000000..8339894 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/RoleResourceTreeVo.java @@ -0,0 +1,15 @@ +package com.volkswagen.mdmds.model.vo; + +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +public class RoleResourceTreeVo { + + private UUID roleId; + private String roleName; + + private List resources; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/RoleToResourceVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/RoleToResourceVo.java new file mode 100644 index 0000000..9f8b067 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/RoleToResourceVo.java @@ -0,0 +1,17 @@ +package com.volkswagen.mdmds.model.vo; + +import lombok.Data; + +import java.util.UUID; + +@Data +public class RoleToResourceVo { + + private UUID roleId; + private String roleName; + + private UUID resId; + private String resName; + private String resUrl; + +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/TicketVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/TicketVo.java new file mode 100644 index 0000000..1538072 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/TicketVo.java @@ -0,0 +1,33 @@ +package com.volkswagen.mdmds.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/21 + */ +@Getter +@Setter +public class TicketVo { + + protected UUID id; + @NotEmpty(message = "工单名称是必填项") + private String ticketName; + private String ticketDetail; + private String createBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date creationDate; + + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + private Date lastModifiedDate; + private ItemStatus status; + private String statusDes; + private Integer total; +} diff --git a/src/main/java/com/volkswagen/mdmds/model/vo/VehicleGroupVo.java b/src/main/java/com/volkswagen/mdmds/model/vo/VehicleGroupVo.java new file mode 100644 index 0000000..70f0604 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/model/vo/VehicleGroupVo.java @@ -0,0 +1,27 @@ +package com.volkswagen.mdmds.model.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import lombok.Data; + +import java.util.Date; +import java.util.UUID; + +@Data +public class VehicleGroupVo { + + protected UUID id; + private String groupName; + private ItemStatus status; + private String statusDes; + private Integer mold; + private Integer total; + + protected String createBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + protected Date creationDate; + protected String lastModifiedBy; + @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="MM/dd/yyyy HH:mm:ss",timezone="GMT+8") + protected Date lastModifiedDate; + +} diff --git a/src/main/java/com/volkswagen/mdmds/out/dto/Vehicle.java b/src/main/java/com/volkswagen/mdmds/out/dto/Vehicle.java new file mode 100644 index 0000000..70e3fc8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/out/dto/Vehicle.java @@ -0,0 +1,13 @@ +package com.volkswagen.mdmds.out.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class Vehicle { + + private List vehicleList; + + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/AuditLogRepository.java b/src/main/java/com/volkswagen/mdmds/repos/AuditLogRepository.java new file mode 100644 index 0000000..d52369e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/AuditLogRepository.java @@ -0,0 +1,13 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.AuditLog; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface AuditLogRepository extends JpaRepository { + + int countById(UUID id); +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/DataCollectionConfigRepository.java b/src/main/java/com/volkswagen/mdmds/repos/DataCollectionConfigRepository.java new file mode 100644 index 0000000..da35063 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/DataCollectionConfigRepository.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.DataCollectionConfig; +import com.volkswagen.mdmds.repos.customize.DataCollectionsConfRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface DataCollectionConfigRepository extends JpaRepository, DataCollectionsConfRepoCustom { + + Optional findByUniqueMd5AndIsDeleted(String md5, Integer isDeleted); + + Optional findByContentMd5AndIsDeleted(String md5, Integer isDeleted); + + List findAllByAdsVersionAndIsDeleted(String adsVersion, Integer isDeleted); + + List findAllBySubscriptionAndIsDeleted(String subscription, Integer isDeleted); + + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/DicAttrValueEnumRepository.java b/src/main/java/com/volkswagen/mdmds/repos/DicAttrValueEnumRepository.java new file mode 100644 index 0000000..cd76277 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/DicAttrValueEnumRepository.java @@ -0,0 +1,9 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.DicAttrValueEnum; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DicAttrValueEnumRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/DicResourceRepository.java b/src/main/java/com/volkswagen/mdmds/repos/DicResourceRepository.java new file mode 100644 index 0000000..d21882f --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/DicResourceRepository.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.DicResource; +import com.volkswagen.mdmds.repos.customize.ResourceInfoRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Repository +public interface DicResourceRepository extends JpaRepository, ResourceInfoRepoCustom { + + @Query(value="select * from dic_resource order by creation_date asc" , nativeQuery=true) + List findResourceItem(); + + @Query(value="select ri.id as roleId, ri.role_name as roleName, dr.id as resId, dr.res_name as resName , dr.res_url as resUrl from role_info_dic_resources ridr " + + "inner join role_info ri on ridr.role_info_id = ri.id " + + "inner join dic_resource dr ON ridr.dic_resources_id = dr.id" , nativeQuery=true) + List> findAllResourceViews(); + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrAdapterRepository.java b/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrAdapterRepository.java new file mode 100644 index 0000000..cec22e4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrAdapterRepository.java @@ -0,0 +1,24 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.DicVehicleAttrAdapter; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface DicVehicleAttrAdapterRepository extends JpaRepository, QuerydslPredicateExecutor { + + DicVehicleAttrAdapter findByAdapterMapping(String adapterMapping); + + @Modifying + @Query(value = "INSERT INTO dic_vehicle_attr_adapter (id, create_by, creation_date, attr_name, adapter_mapping, adapter_key, adapter_value) " + + "VALUES (:#{#adapter.id}, :#{#adapter.createBy}, :#{#adapter.creationDate}, :#{#adapter.attrName}, :#{#adapter.adapterMapping}, :#{#adapter.adapterKey}, :#{#adapter.adapterValue}) " + + "ON CONFLICT (adapter_mapping) DO NOTHING", nativeQuery = true) + void saveIgnoreConflict(@Param("adapter") DicVehicleAttrAdapter adapter); + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepository.java b/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepository.java new file mode 100644 index 0000000..9c9e2d3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepository.java @@ -0,0 +1,34 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.entity.DicVehicleAttr; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface DicVehicleAttrRepository extends JpaRepository, QuerydslPredicateExecutor { + + @Modifying + @Query( + value = "truncate table dic_vehicle_attr", + nativeQuery = true + ) + void truncateTable(); + + List findBy(); + + List findBy(Class projection); + + List findByStatus(ItemStatus status); + + List findByAttrName(String attrName); + + List findByMappingName(String mappingName); +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/GroupConfigurationRepository.java b/src/main/java/com/volkswagen/mdmds/repos/GroupConfigurationRepository.java new file mode 100644 index 0000000..b9cf7d3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/GroupConfigurationRepository.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.GroupConfiguration; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface GroupConfigurationRepository extends JpaRepository { + + Optional findByGroupId(UUID groupId); + + List findAllByDccIdIn(List idList); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/GroupDccRecordRepository.java b/src/main/java/com/volkswagen/mdmds/repos/GroupDccRecordRepository.java new file mode 100644 index 0000000..45b569c --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/GroupDccRecordRepository.java @@ -0,0 +1,9 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.GroupDccRecord; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface GroupDccRecordRepository extends JpaRepository { +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/GroupSpecificationRepository.java b/src/main/java/com/volkswagen/mdmds/repos/GroupSpecificationRepository.java new file mode 100644 index 0000000..3f65820 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/GroupSpecificationRepository.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.GroupSpecification; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface GroupSpecificationRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/GroupVehicleRepository.java b/src/main/java/com/volkswagen/mdmds/repos/GroupVehicleRepository.java new file mode 100644 index 0000000..ace0944 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/GroupVehicleRepository.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.GroupVehicle; +import com.volkswagen.mdmds.repos.customize.GroupVehicleRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface GroupVehicleRepository extends JpaRepository, GroupVehicleRepoCustom { + + Optional findByGroupId(UUID id); + + void deleteByGroupId(UUID id); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/RoleInfoRepository.java b/src/main/java/com/volkswagen/mdmds/repos/RoleInfoRepository.java new file mode 100644 index 0000000..dfbc5fd --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/RoleInfoRepository.java @@ -0,0 +1,29 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.RoleInfo; +import com.volkswagen.mdmds.repos.customize.RoleInfoRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface RoleInfoRepository extends JpaRepository, RoleInfoRepoCustom { + + List> findByRoleNameIn(List roleNameList); + + @Query(value="select * from role_info order by creation_date asc" , nativeQuery=true) + List findRoleItem(); + + @Query(value="select ri.id as roleId, ri.role_name as roleName, dr.id as resId, dr.res_name as resName , dr.res_url as resUrl from role_info_dic_resources ridr " + + "inner join role_info ri on ridr.role_info_id = ri.id " + + "inner join dic_resource dr ON ridr.dic_resources_id = dr.id " + + "where ri.role_name IN(:roleNameList)" , nativeQuery=true) + List> findResourceInRoleName(@Param("roleNameList") List roleNameList); + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/TicketRepository.java b/src/main/java/com/volkswagen/mdmds/repos/TicketRepository.java new file mode 100644 index 0000000..41c73a1 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/TicketRepository.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.Ticket; +import com.volkswagen.mdmds.repos.customize.TicketRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface TicketRepository extends JpaRepository, TicketRepoCustom { + + Ticket findOneByIdAndIsDeleted(UUID id, Integer isDeleted); + + List findByIdIn(List idList); + + List findAllByTicketNameEqualsAndIsDeleted(String ticketName, Integer isDeleted); +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/TicketVehicleRepository.java b/src/main/java/com/volkswagen/mdmds/repos/TicketVehicleRepository.java new file mode 100644 index 0000000..76d8511 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/TicketVehicleRepository.java @@ -0,0 +1,16 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.TicketVehicle; +import com.volkswagen.mdmds.repos.customize.TicketVehicleRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +@Repository +public interface TicketVehicleRepository extends JpaRepository, TicketVehicleRepoCustom { + + + + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/UserInfoRepository.java b/src/main/java/com/volkswagen/mdmds/repos/UserInfoRepository.java new file mode 100644 index 0000000..086d8ae --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/UserInfoRepository.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.UserInfo; +import com.volkswagen.mdmds.repos.customize.UserInfoRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@Repository +public interface UserInfoRepository extends JpaRepository, UserInfoRepoCustom { + + Optional findByUserName(String userName); + + Optional findById(UUID id); + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/VehicleGroupRepository.java b/src/main/java/com/volkswagen/mdmds/repos/VehicleGroupRepository.java new file mode 100644 index 0000000..1a1e6e5 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/VehicleGroupRepository.java @@ -0,0 +1,28 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.VehicleGroup; +import com.volkswagen.mdmds.repos.customize.VehicleGroupRepoCustom; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface VehicleGroupRepository extends JpaRepository, VehicleGroupRepoCustom { + + VehicleGroup findOneByIdAndIsDeleted(UUID id, Integer isDeleted); + + List findAllByIdInAndIsDeleted(List idList, Integer isDeleted); + + List findAllByGroupNameEqualsAndIsDeleted(String groupName, Integer isDeleted); + + List findAllByIdInAndIsDeletedAndStatus(List idList, Integer isDeleted, ItemStatus status); + +// @Query(value="select vg.id as groupId, vg.group_name as groupName from vehicle_group vg where vg.id IN(" + +// "select gc.group_id from group_configuration gc where gc.dcc_id IN(:dccIdList)" + +// ") " + +// "and vg.is_deleted=0 and vg.status=0" , nativeQuery=true) + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/VehicleInfoRepository.java b/src/main/java/com/volkswagen/mdmds/repos/VehicleInfoRepository.java new file mode 100644 index 0000000..687a887 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/VehicleInfoRepository.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.entity.VehicleInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface VehicleInfoRepository extends JpaRepository { + + Optional findByVin(String vin); + + List findByVidIn(List vidList); + + List findByVinIn(List vinList); + +} \ No newline at end of file diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/DataCollectionsConfRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/DataCollectionsConfRepoCustom.java new file mode 100644 index 0000000..155dcbb --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/DataCollectionsConfRepoCustom.java @@ -0,0 +1,18 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.PolicyBriefInfoDTO; +import com.volkswagen.mdmds.model.param.PolicySearchParam; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +/** + * @author Shuo Ding + * @since 2023/3/14 + */ +public interface DataCollectionsConfRepoCustom { + + Page findAllDccPageable(Pageable pageable); + + Page searchPageable(Pageable pageable, PolicySearchParam param); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/GroupVehicleRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/GroupVehicleRepoCustom.java new file mode 100644 index 0000000..09bbbca --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/GroupVehicleRepoCustom.java @@ -0,0 +1,13 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.UUID; + +public interface GroupVehicleRepoCustom { + + Page findAllVehiclePageable(Pageable pageable, UUID groupId); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/ResourceInfoRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/ResourceInfoRepoCustom.java new file mode 100644 index 0000000..3f2d84d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/ResourceInfoRepoCustom.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.ResourceInfoDTO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface ResourceInfoRepoCustom { + + Page findAllResourceInfoPageable(Pageable pageable); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/RoleInfoRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/RoleInfoRepoCustom.java new file mode 100644 index 0000000..98fc3c4 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/RoleInfoRepoCustom.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.RoleInfoDTO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface RoleInfoRepoCustom { + + Page findAllRoleInfoPageable(Pageable pageable); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/TicketRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/TicketRepoCustom.java new file mode 100644 index 0000000..03ea66e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/TicketRepoCustom.java @@ -0,0 +1,15 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.TicketBriefInfoDTO; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.vo.TicketVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface TicketRepoCustom { + + Page findAllTicketPageable(Pageable pageable); + + Page findAllTicketPageable(Pageable pageable, TicketParam param); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/TicketVehicleRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/TicketVehicleRepoCustom.java new file mode 100644 index 0000000..3a5025b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/TicketVehicleRepoCustom.java @@ -0,0 +1,13 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.UUID; + +public interface TicketVehicleRepoCustom { + + Page findAllVehiclePageable(Pageable pageable, UUID groupId); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/UserInfoRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/UserInfoRepoCustom.java new file mode 100644 index 0000000..1591af0 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/UserInfoRepoCustom.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.UserInfoDTO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface UserInfoRepoCustom { + + Page findAllUserInfoPageable(Pageable pageable); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/VehicleGroupRepoCustom.java b/src/main/java/com/volkswagen/mdmds/repos/customize/VehicleGroupRepoCustom.java new file mode 100644 index 0000000..0c1ffe0 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/VehicleGroupRepoCustom.java @@ -0,0 +1,15 @@ +package com.volkswagen.mdmds.repos.customize; + +import com.volkswagen.mdmds.model.dto.GroupReturnDTO; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface VehicleGroupRepoCustom { + + Page findAllGroupPageable(Pageable pageable); + + Page findAllVehicleGroupPageable(Pageable pageable, VehicleGroupParam param); + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/DataCollectionsConfRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/DataCollectionsConfRepoCustomImpl.java new file mode 100644 index 0000000..2032352 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/DataCollectionsConfRepoCustomImpl.java @@ -0,0 +1,138 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.PolicyBriefInfoDTO; +import com.volkswagen.mdmds.model.entity.DataCollectionConfig; +import com.volkswagen.mdmds.model.entity.QDataCollectionConfig; +import com.volkswagen.mdmds.model.param.PolicySearchParam; +import com.volkswagen.mdmds.repos.customize.DataCollectionsConfRepoCustom; +import jakarta.persistence.EntityManager; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/3/14 + */ +public class DataCollectionsConfRepoCustomImpl implements DataCollectionsConfRepoCustom { + + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public DataCollectionsConfRepoCustomImpl(JpaContext jpaContext) { + this.entityManager =jpaContext.getEntityManagerByManagedType(DataCollectionConfig.class); + this.queryFactory=new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllDccPageable(Pageable pageable) { + QDataCollectionConfig qDataCollectionConfig=QDataCollectionConfig.dataCollectionConfig; + //使用querydsl查询指定字段出来 + QueryResults results = queryFactory.from(qDataCollectionConfig) + .select(Projections.fields( + PolicyBriefInfoDTO.class, + qDataCollectionConfig.id, + qDataCollectionConfig.subscription, + qDataCollectionConfig.adsVersion, + qDataCollectionConfig.eventList, + qDataCollectionConfig.dccDetail, + qDataCollectionConfig.creationDate, + qDataCollectionConfig.description + )).offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(qDataCollectionConfig.creationDate.desc()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + + @Override + public Page searchPageable(Pageable pageable, PolicySearchParam param) { + QDataCollectionConfig qDataCollectionConfig = QDataCollectionConfig.dataCollectionConfig; + QBean bean = Projections.bean( + PolicyBriefInfoDTO.class, + qDataCollectionConfig.id, + qDataCollectionConfig.adsVersion, + qDataCollectionConfig.subscription, + qDataCollectionConfig.description, + qDataCollectionConfig.dccDetail, + qDataCollectionConfig.eventList, + qDataCollectionConfig.taskId, + qDataCollectionConfig.apiForm, + qDataCollectionConfig.startTime, + qDataCollectionConfig.endTime, + qDataCollectionConfig.createBy, + qDataCollectionConfig.creationDate, + qDataCollectionConfig.lastModifiedDate, + qDataCollectionConfig.lastModifiedBy + ); + JPAQuery query = queryFactory.select(bean).from(qDataCollectionConfig) + .where(qDataCollectionConfig.isDeleted.eq(0)); + if(ObjectUtils.isNotEmpty(param.getApiForm())) { + query.where(qDataCollectionConfig.apiForm.likeIgnoreCase("%" + param.getApiForm() + "%")); + } + if(ObjectUtils.isNotEmpty(param.getAdsVersion())) { + query.where(qDataCollectionConfig.adsVersion.likeIgnoreCase("%" + param.getAdsVersion() + "%")); + } + if(ObjectUtils.isNotEmpty(param.getSubscription())) { + query.where(qDataCollectionConfig.subscription.likeIgnoreCase("%" + param.getSubscription() + "%")); + } + if(ObjectUtils.isNotEmpty(param.getSortField()) && ObjectUtils.isNotEmpty(param.getSortOrder())) { + String sortField = param.getSortField(); + String sortOrder = param.getSortOrder(); + if(sortOrder.equalsIgnoreCase("asc")) { + queryOrderByAsc(query, sortField, qDataCollectionConfig); + } else if(sortOrder.equalsIgnoreCase("desc")) { + queryOrderByDesc(query, sortField, qDataCollectionConfig); + } + } else { + query.orderBy(qDataCollectionConfig.creationDate.desc()); + } + QueryResults results = query.orderBy(qDataCollectionConfig.lastModifiedDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + + private void queryOrderByAsc(JPAQuery query, String sortField, QDataCollectionConfig qDataCollectionConfig) { + if(sortField.equals("adsVersion")) { + query.orderBy(qDataCollectionConfig.adsVersion.asc()); + } else if(sortField.equals("subscription")) { + query.orderBy(qDataCollectionConfig.subscription.asc()); + } else if(sortField.equals("description")) { + query.orderBy(qDataCollectionConfig.description.asc()); + } else if(sortField.equals("creationDate")) { + query.orderBy(qDataCollectionConfig.creationDate.asc()); + } else { + query.orderBy(qDataCollectionConfig.creationDate.desc()); + } + } + private void queryOrderByDesc(JPAQuery query, String sortField, QDataCollectionConfig qDataCollectionConfig) { + if(sortField.equals("adsVersion")) { + query.orderBy(qDataCollectionConfig.adsVersion.desc()); + } else if(sortField.equals("subscription")) { + query.orderBy(qDataCollectionConfig.subscription.desc()); + } else if(sortField.equals("description")) { + query.orderBy(qDataCollectionConfig.description.desc()); + } else if(sortField.equals("creationDate")) { + query.orderBy(qDataCollectionConfig.creationDate.desc()); + } else { + query.orderBy(qDataCollectionConfig.creationDate.desc()); + } + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/GroupVehicleRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/GroupVehicleRepoCustomImpl.java new file mode 100644 index 0000000..27992c7 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/GroupVehicleRepoCustomImpl.java @@ -0,0 +1,54 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.entity.GroupVehicle; +import com.volkswagen.mdmds.model.entity.QGroupVehicle; +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import com.volkswagen.mdmds.repos.customize.GroupVehicleRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; +import java.util.UUID; + +public class GroupVehicleRepoCustomImpl implements GroupVehicleRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public GroupVehicleRepoCustomImpl(JpaContext jpaContext) { + this.entityManager = jpaContext.getEntityManagerByManagedType(GroupVehicle.class); + this.queryFactory = new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllVehiclePageable(Pageable pageable, UUID groupId) { + QGroupVehicle qGroupVehicle = QGroupVehicle.groupVehicle; + + QBean bean = Projections.bean( + GroupVehicleInfoPojo.class, + qGroupVehicle.groupId, + qGroupVehicle.vid, + qGroupVehicle.vin, + qGroupVehicle.infos, + qGroupVehicle.statusCode, + qGroupVehicle.message + ); + QueryResults results = queryFactory.select(bean).from(qGroupVehicle) + .where(qGroupVehicle.groupId.eq(groupId)) + .orderBy(qGroupVehicle.creationDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/ResourceInfoRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/ResourceInfoRepoCustomImpl.java new file mode 100644 index 0000000..fda5b8d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/ResourceInfoRepoCustomImpl.java @@ -0,0 +1,50 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.ResourceInfoDTO; +import com.volkswagen.mdmds.model.entity.DicResource; +import com.volkswagen.mdmds.model.entity.QDicResource; +import com.volkswagen.mdmds.repos.customize.ResourceInfoRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +public class ResourceInfoRepoCustomImpl implements ResourceInfoRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public ResourceInfoRepoCustomImpl(JpaContext jpaContext) { + this.entityManager = jpaContext.getEntityManagerByManagedType(DicResource.class); + this.queryFactory = new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllResourceInfoPageable(Pageable pageable) { + QDicResource qResourceInfo = QDicResource.dicResource; + QueryResults results = queryFactory.from(qResourceInfo) + .select(Projections.fields( + ResourceInfoDTO.class, + qResourceInfo.id, + qResourceInfo.resName, + qResourceInfo.resUrl, + qResourceInfo.createBy, + qResourceInfo.creationDate, + qResourceInfo.lastModifiedBy, + qResourceInfo.lastModifiedDate + )).offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(qResourceInfo.lastModifiedDate.desc()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/RoleInfoRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/RoleInfoRepoCustomImpl.java new file mode 100644 index 0000000..1a46255 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/RoleInfoRepoCustomImpl.java @@ -0,0 +1,50 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.RoleInfoDTO; +import com.volkswagen.mdmds.model.entity.QRoleInfo; +import com.volkswagen.mdmds.model.entity.RoleInfo; +import com.volkswagen.mdmds.repos.customize.RoleInfoRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +public class RoleInfoRepoCustomImpl implements RoleInfoRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public RoleInfoRepoCustomImpl(JpaContext jpaContext) { + this.entityManager = jpaContext.getEntityManagerByManagedType(RoleInfo.class); + this.queryFactory = new JPAQueryFactory(this.entityManager); + } + + + @Override + public Page findAllRoleInfoPageable(Pageable pageable) { + QRoleInfo qRoleInfo = QRoleInfo.roleInfo; + QueryResults results = queryFactory.from(qRoleInfo) + .select(Projections.fields( + RoleInfoDTO.class, + qRoleInfo.id, + qRoleInfo.roleName, + qRoleInfo.createBy, + qRoleInfo.creationDate, + qRoleInfo.lastModifiedBy, + qRoleInfo.lastModifiedDate + )).offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(qRoleInfo.creationDate.asc()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketRepoCustomImpl.java new file mode 100644 index 0000000..1ab6aad --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketRepoCustomImpl.java @@ -0,0 +1,97 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.TicketBriefInfoDTO; +import com.volkswagen.mdmds.model.entity.DataCollectionConfig; +import com.volkswagen.mdmds.model.entity.QTicket; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.vo.TicketVo; +import com.volkswagen.mdmds.repos.customize.TicketRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +public class TicketRepoCustomImpl implements TicketRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory jpaQueryFactory; + + public TicketRepoCustomImpl(JpaContext jpaContext) { + this.entityManager =jpaContext.getEntityManagerByManagedType(DataCollectionConfig.class); + this.jpaQueryFactory=new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllTicketPageable(Pageable pageable) { + QTicket qTicket = QTicket.ticket; + //使用querydsl查询指定字段出来 + QueryResults results = jpaQueryFactory.from(qTicket) + .select(Projections.fields( + TicketBriefInfoDTO.class, + qTicket.id, + qTicket.ticketName, + qTicket.ticketDetail, + qTicket.status, + qTicket.total, + qTicket.createBy, + qTicket.creationDate, + qTicket.lastModifiedDate + )).where(qTicket.isDeleted.eq(0)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(qTicket.creationDate.desc()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + + @Override + public Page findAllTicketPageable(Pageable pageable, TicketParam param) { + QTicket qTicket = QTicket.ticket; + QBean bean = Projections.bean( + TicketVo.class, + qTicket.id, + qTicket.ticketName, + qTicket.ticketDetail, + qTicket.status, + qTicket.total, + qTicket.createBy, + qTicket.creationDate, + qTicket.lastModifiedDate + ); + JPAQuery query = jpaQueryFactory.select(bean).from(qTicket) + .where(qTicket.isDeleted.eq(0)); + if(param.getTicketName() != null && param.getTicketName().length() > 0) { + query.where(qTicket.ticketName.likeIgnoreCase("%" + param.getTicketName() + "%")); + } + if(param.getStatus() != null) { + query.where(qTicket.status.eq(param.getStatus())); + } +// if(param.getTotalMin() != null && param.getTotalMin().length() > 0) { +// query.where(qTicket.total.goe(Integer.valueOf(param.getTotalMin()))); +// } +// if(param.getTotalMax() != null && param.getTotalMax().length() > 0) { +// query.where(qTicket.total.loe(Integer.valueOf(param.getTotalMax()))); +// } + if(param.getVin() != null && param.getVin().length() > 0) { + query.where(qTicket.vines.contains(param.getVin())); + } + QueryResults results = query.orderBy(qTicket.lastModifiedDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketVehicleRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketVehicleRepoCustomImpl.java new file mode 100644 index 0000000..c60f761 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/TicketVehicleRepoCustomImpl.java @@ -0,0 +1,56 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.entity.*; +import com.volkswagen.mdmds.model.entity.QTicketVehicle; +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import com.volkswagen.mdmds.repos.customize.TicketVehicleRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; +import java.util.UUID; + +public class TicketVehicleRepoCustomImpl implements TicketVehicleRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public TicketVehicleRepoCustomImpl(JpaContext jpaContext) { + this.entityManager =jpaContext.getEntityManagerByManagedType(TicketVehicle.class); + this.queryFactory=new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllVehiclePageable(Pageable pageable, UUID ticketId) { + QTicketVehicle qTicketVehicle = QTicketVehicle.ticketVehicle; + + QBean bean = Projections.bean( + TicketVehicleInfoPojo.class, + qTicketVehicle.ticketId, + qTicketVehicle.vid, + qTicketVehicle.vin, + qTicketVehicle.infos, + qTicketVehicle.statusCode, + qTicketVehicle.message +// qVehicleInfo.vin, +// qVehicleInfo.infos + ); + QueryResults results = queryFactory.select(bean).from(qTicketVehicle) +// .leftJoin(qVehicleInfo).on(qTicketVehicle.vid.eq(qVehicleInfo.vid)) + .where(qTicketVehicle.ticketId.eq(ticketId)) + .orderBy(qTicketVehicle.creationDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/UserInfoRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/UserInfoRepoCustomImpl.java new file mode 100644 index 0000000..8c0f4ad --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/UserInfoRepoCustomImpl.java @@ -0,0 +1,48 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.UserInfoDTO; +import com.volkswagen.mdmds.model.entity.QUserInfo; +import com.volkswagen.mdmds.model.entity.UserInfo; +import com.volkswagen.mdmds.repos.customize.UserInfoRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +public class UserInfoRepoCustomImpl implements UserInfoRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory queryFactory; + + public UserInfoRepoCustomImpl(JpaContext jpaContext) { + this.entityManager = jpaContext.getEntityManagerByManagedType(UserInfo.class); + this.queryFactory=new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllUserInfoPageable(Pageable pageable) { + QUserInfo qUserInfo = QUserInfo.userInfo; + QueryResults results = queryFactory.from(qUserInfo) + .select(Projections.fields( + UserInfoDTO.class, + qUserInfo.id, + qUserInfo.userName, + qUserInfo.email, + qUserInfo.roles, + qUserInfo.status, + qUserInfo.lastModifiedDate + )).offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(qUserInfo.lastModifiedDate.desc()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/repos/customize/impl/VehicleGroupRepoCustomImpl.java b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/VehicleGroupRepoCustomImpl.java new file mode 100644 index 0000000..500ef11 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/repos/customize/impl/VehicleGroupRepoCustomImpl.java @@ -0,0 +1,106 @@ +package com.volkswagen.mdmds.repos.customize.impl; + +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.jpa.impl.JPAQuery; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.volkswagen.mdmds.model.dto.GroupReturnDTO; +import com.volkswagen.mdmds.model.entity.QGroupSpecification; +import com.volkswagen.mdmds.model.entity.QVehicleGroup; +import com.volkswagen.mdmds.model.entity.VehicleGroup; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import com.volkswagen.mdmds.repos.customize.VehicleGroupRepoCustom; +import jakarta.persistence.EntityManager; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaContext; + +import java.util.List; + +public class VehicleGroupRepoCustomImpl implements VehicleGroupRepoCustom { + + private EntityManager entityManager; + private final JPAQueryFactory jpaQueryFactory; + + public VehicleGroupRepoCustomImpl(JpaContext jpaContext) { + this.entityManager =jpaContext.getEntityManagerByManagedType(VehicleGroup.class); + this.jpaQueryFactory=new JPAQueryFactory(this.entityManager); + } + + @Override + public Page findAllGroupPageable(Pageable pageable) { + QVehicleGroup qVehicleGroup = QVehicleGroup.vehicleGroup; + QGroupSpecification qGroupSpecification = QGroupSpecification.groupSpecification; + + QBean bean = Projections.bean( + GroupReturnDTO.class, + qVehicleGroup.id, + qVehicleGroup.groupName, + qVehicleGroup.status, + qVehicleGroup.createBy, + qVehicleGroup.creationDate, + qVehicleGroup.lastModifiedBy, + qVehicleGroup.lastModifiedDate, + qVehicleGroup.mold, + qVehicleGroup.total, + QGroupSpecification.groupSpecification.specificationJson, + QGroupSpecification.groupSpecification.tags + ); + + QueryResults results = jpaQueryFactory.select(bean).from(qVehicleGroup) + .leftJoin(qGroupSpecification).on(qVehicleGroup.groupSpecification.id.eq(qGroupSpecification.id)) + .where(qVehicleGroup.isDeleted.eq(0)) + .orderBy(qVehicleGroup.lastModifiedDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } + + public Page findAllVehicleGroupPageable(Pageable pageable, VehicleGroupParam param) { + QVehicleGroup qVehicleGroup = QVehicleGroup.vehicleGroup; + QGroupSpecification qGroupSpecification = QGroupSpecification.groupSpecification; + QBean bean = Projections.bean( + VehicleGroupVo.class, + qVehicleGroup.id, + qVehicleGroup.groupName, + qVehicleGroup.status, + qVehicleGroup.createBy, + qVehicleGroup.creationDate, + qVehicleGroup.lastModifiedBy, + qVehicleGroup.lastModifiedDate, + qVehicleGroup.mold, + qVehicleGroup.total, + QGroupSpecification.groupSpecification.specificationJson, + QGroupSpecification.groupSpecification.tags + ); + JPAQuery query = jpaQueryFactory.select(bean).from(qVehicleGroup) + .leftJoin(qGroupSpecification).on(qVehicleGroup.groupSpecification.id.eq(qGroupSpecification.id)) + .where(qVehicleGroup.isDeleted.eq(0)); + if(param.getGroupName() != null && param.getGroupName().length() > 0) { + query.where(qVehicleGroup.groupName.likeIgnoreCase("%" + param.getGroupName() + "%")); + } + if(param.getStatus() != null) { + query.where(qVehicleGroup.status.eq(param.getStatus())); + } + if(param.getTotalMin() != null && param.getTotalMin().length() > 0) { + query.where(qVehicleGroup.total.goe(Integer.valueOf(param.getTotalMin()))); + } + if(param.getTotalMax() != null && param.getTotalMax().length() > 0) { + query.where(qVehicleGroup.total.loe(Integer.valueOf(param.getTotalMax()))); + } + QueryResults results = query.orderBy(qVehicleGroup.lastModifiedDate.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetchResults(); + List contents = results.getResults(); + long total = results.getTotal(); + return new PageImpl<>(contents, pageable, total); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/AttributeService.java b/src/main/java/com/volkswagen/mdmds/service/AttributeService.java new file mode 100644 index 0000000..376522e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/AttributeService.java @@ -0,0 +1,52 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.AttrWithValuesDTO; +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.dto.UploadDataDTO; +import com.volkswagen.mdmds.model.entity.DicVehicleAttr; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +public interface AttributeService { + + DicVehicleAttr addNewAttr(AttributeDTO attributeDTO); + + List getAllAttrs(); + + List getAttrViews(AttributeDTO attributeDTO); + + DicVehicleAttr changeAttributeStatus(UUID id, AttributeDTO dto); + + DicVehicleAttr deleteAttributeById(UUID id); + + DicVehicleAttr updateVehicleAttr(UUID id, AttributeDTO dto); + + void clearTable(); + + void verification(); + + String verificationAttrName(AttributeDTO dto); + + void getAttrValue(); + + List getAllAttrValueMap(); + + /** + * + * @param file + */ + void uploadAttributeFiled(MultipartFile file); + + ResponseEntity uploadAttributeFieldCheckData(MultipartFile file); + + void uploadAttribute(UploadDataDTO uploadDataDTO); + + void syncVehicleKeyAndValue(); +} diff --git a/src/main/java/com/volkswagen/mdmds/service/AuditService.java b/src/main/java/com/volkswagen/mdmds/service/AuditService.java new file mode 100644 index 0000000..726c18d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/AuditService.java @@ -0,0 +1,11 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.AuditDTO; + +public interface AuditService { + + void insertOne(AuditDTO auditDTO); + + int countByCondition(String id); + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/GroupService.java b/src/main/java/com/volkswagen/mdmds/service/GroupService.java new file mode 100644 index 0000000..9adf8fa --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/GroupService.java @@ -0,0 +1,126 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.VehicleGroup; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/3/16 + */ +public interface GroupService { + + /** + * 通过组名来创建新的分组 + * + * @param groupName 组名,只能包含中英文字符和汉字,不能包含特殊字符 + * @return 创建成功后数据库中的分组ID + */ + UUID createNewGroupByName(String groupName); + + /** + * 更新分组的信息 + *

+ * 能且只能编辑一次,第二次更新就需要报错 + * + * @param dto 主要是分组条件是分组条件、标签 + */ + VehicleGroup updateGroupSpecInfo(GroupDetailInfoDTO dto); + + /** + * 创建分组关联车辆信息 + * @param vehicleGroup + * @param dto + */ + void updateGroupVehicleByCriteria(List vidList, VehicleGroup vehicleGroup, GroupDetailInfoDTO dto); + + /** + * 更新分组关联车辆VIN + * @param dto + * @return + */ + VehicleGroup updateGroupVinAndInfo(GroupDetailInfoDTO dto); + + /** + * 更新车辆分组的配置 + * @param groupId + * @param dccId + */ + void updateGroupConfiguration(UUID groupId, UUID dccId); + + /** + * 解除车辆分组的配置 + * @param groupId + */ + void unbindGroupConfiguration(UUID groupId); + + + /** + * 分组车辆的简要信息 + * @param pageable + * @return + */ + Page pageableBriefGroup(Pageable pageable); + Page pageableGroup(int pageNo, int pageSize, VehicleGroupParam param); + + /** + * 根据分组ID删除分组 + * @param id + * @return + */ + VehicleGroup deleteGroupById(UUID id); + + void deletedGroupByIds(List idList); + + /** + * 查询车辆分组的详细信息 + * @param id + * @return + */ + GroupDetailInfoDTO getGroupDetailInfo(UUID id); + + /** + * 根据分组条件报错关联的车辆ID并通过车辆ID查询车辆信息 + * @param id + * @param groupDetailInfoDTO + */ + void getVehicleIds(UUID id, GroupDetailInfoDTO groupDetailInfoDTO); + + /** + * 根据车辆条件查询车辆vidList + * @param id + * @param dto + * @return + */ + List getAllVIDs(UUID id, GroupParamsDTO dto); + + /** + * 根据车辆vidList查询车辆信息 + * @param id + * @param dto + * @return + */ + List getVehicleViews(UUID id, GroupParamsDTO dto); + + /** + * 获取分组下的车辆信息 + * @param pageable + * @return + */ + Page pageableVehicleInfo(Pageable pageable, UUID groupId); + + + /** + * 创建分组关联车辆信息 + * @param vehicleGroup + * @param dto + */ + void updateGroupVehicleByVIN(VehicleGroup vehicleGroup, GroupParamsDTO dto); +} diff --git a/src/main/java/com/volkswagen/mdmds/service/LinkDTService.java b/src/main/java/com/volkswagen/mdmds/service/LinkDTService.java new file mode 100644 index 0000000..38ee4e1 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/LinkDTService.java @@ -0,0 +1,78 @@ +package com.volkswagen.mdmds.service; + +import org.modelmapper.internal.util.CopyOnWriteLinkedHashMap; +import org.springframework.util.MultiValueMap; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** + * @author Shuo Ding + * @since 2023/3/20 + *

+ * 调用VW的DitigitalTwin完成部分关键数据的获取 + * 1、车辆所有属性 + * 2、车辆所有属性所包含的枚举值 + * 3、获取车辆详细信息 + */ +public interface LinkDTService { + + + /** + * 根据车辆唯一ID,查询车辆的具体信息 + * + * @param vehicleIds 车辆id,不是vin,是系统中的唯一ID + * @return 车辆具体信息,JSON + */ + Object getVehicleInfo(List vehicleIds) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException; + CopyOnWriteLinkedHashMap getVehicleInfoByVid(List vehicleIds) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException; + + /** + * 根据车辆VID获取车型信息 + * @param vid + * @return + * @throws NoSuchAlgorithmException + * @throws KeyManagementException + * @throws IOException + * @throws InterruptedException + */ + Object getVehicleInfo(String vid) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException; + + /** + * 根据查询条件返回车辆的id + *

+ * DT接受的传参是mongodb的query dsl格式 + * MDMDS前端返回的是{"车辆属性":"车辆属性值","车辆属性":"车辆属性值"} + * 需要将收到的传参转换为mongodb的格式 + *

+ * 按照当前的设计,前端传回的车辆属性,都是and关系,没有or的关系 + * 并且一个车辆属性只能有一个值,比如车身颜色color,在当前的设计中,只能有一个颜色 + * 不支持一个分组中存在多种颜色不一样的车 + * + * @param condition json格式(kV)的车辆属性条件 + * @return 所有符合条件的车辆ID + */ + Object getVehicleIdByCondition(String condition) throws IOException, InterruptedException, ExecutionException, NoSuchAlgorithmException, KeyManagementException; + + /** + * 从DT中获取当前系统中所有存在的车辆属性名称 + * + * @return 车辆属性名称列表 + */ + Object getAllAttributes() throws IOException, InterruptedException, ExecutionException, NoSuchAlgorithmException, KeyManagementException; + + /** + * 根据车辆属性名称,查询该属性下所有的可能值 + *

+ * 相当于DT系统内返回了select distinct attr_value from DT where attr_name=? + * + * @param params + * @return + */ + Object getAllEnumForAttribute(MultiValueMap params) throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException; + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/LinkHWService.java b/src/main/java/com/volkswagen/mdmds/service/LinkHWService.java new file mode 100644 index 0000000..d77641d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/LinkHWService.java @@ -0,0 +1,31 @@ +package com.volkswagen.mdmds.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.model.param.PolicyParam; +import com.volkswagen.mdmds.model.param.PolicyReqParam; + +public interface LinkHWService { + + /** + * Get event list by ADS Version + * @param adsVersion ADS Version + * @return Event List Info + */ + JSONArray getEventListByAdsVersion(String adsVersion); + + /** + * Get configuration1 + * @param param Common + * @return Configuration Info + */ + JSONObject getPolicyByAdsVersionAndEvent(PolicyParam param); + + /** + * Get configuration2 + * @param param On-Demand Pull + * @return Configuration Info + */ + JSONObject getPolicyByOnDemandPull(PolicyReqParam param); + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/LinkMSService.java b/src/main/java/com/volkswagen/mdmds/service/LinkMSService.java new file mode 100644 index 0000000..e58ad52 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/LinkMSService.java @@ -0,0 +1,19 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.MappingAllFieldDTO; + +import java.util.List; + +/** + * ADSVersion和MDSVersion映射 + * + * @author Chen Li + * @since 4/11/2025 + */ +public interface LinkMSService { + + MappingAllFieldDTO getAllMappings() throws Exception; + + List getADSVersion(String mdcVersion) throws Exception; + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/LinkVWACService.java b/src/main/java/com/volkswagen/mdmds/service/LinkVWACService.java new file mode 100644 index 0000000..8937ac8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/LinkVWACService.java @@ -0,0 +1,23 @@ +package com.volkswagen.mdmds.service; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +public interface LinkVWACService { + + /** + * 根据VIN获取VID + * @param vin + * @return + */ + Object getVIDByVIN(String vin) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException; + + /** + * 根据VID获取VIN + * @param vid + * @return + */ + Object getVINByVID(String vid) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException; + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/PolicyService.java b/src/main/java/com/volkswagen/mdmds/service/PolicyService.java new file mode 100644 index 0000000..2c3d4c9 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/PolicyService.java @@ -0,0 +1,48 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.DccDTO; +import com.volkswagen.mdmds.model.dto.PolicyBriefInfoDTO; +import com.volkswagen.mdmds.model.dto.PolicyParamsDTO; +import com.volkswagen.mdmds.model.entity.DataCollectionConfig; +import com.volkswagen.mdmds.model.param.PolicyCreateParam; +import com.volkswagen.mdmds.model.param.PolicySaveParam; +import com.volkswagen.mdmds.model.param.PolicySearchParam; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.UUID; + +/** + * @author Shuo Ding + * @since 2023/3/7 + */ +public interface PolicyService { + + /** + * 接收并保存数据收集配置信息 + * + *需要执行核心的几步: + * 1、格式化来自EHRM的配置信息 + * 2、提取软件版本号和事件列表 + * 3、计算配置项的md5值,重复项不予存储,针对更新项进行更新 + * + * HW目前给的样例中有sha值,需要确认他们对于这个sha值的使用方式 + * @param dto + */ + DataCollectionConfig upsertOneDCC(DccDTO dto); + + Page pageableBriefPolicy(Pageable pageable); + + Page searchPolicyPage(PolicySearchParam param); + + PolicyBriefInfoDTO getPolicyInfo(UUID id); + + List getPolicyViews(PolicyParamsDTO dto); + + void save(PolicySaveParam param); + + void create(PolicyCreateParam param); + + void deleteConfigurationByIds(List idList); +} diff --git a/src/main/java/com/volkswagen/mdmds/service/TicketService.java b/src/main/java/com/volkswagen/mdmds/service/TicketService.java new file mode 100644 index 0000000..50f17c2 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/TicketService.java @@ -0,0 +1,66 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.Ticket; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.param.TicketUpdateParam; +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.TicketVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.UUID; + +public interface TicketService { + + Ticket createTicket(TicketBriefInfoDTO dto); + + Page pageableBriefTicket(Pageable pageable); + Page pageableTicket(int pageNo, int pageSize, TicketParam param); + + Ticket addVinToTicket(UUID id, String vin); + + Ticket updateTicketDescription(UUID id, TicketUpdateParam dto); + + Ticket changeTicketStatus(UUID id, TicketBriefInfoDTO dto); + + Ticket deleteTicketById(UUID id); + + /** + * 批量标识删除 + * @param idList + */ + void deleteTicketByIds(List idList); + + TicketDetailDTO getTicketDetail(UUID id); + + /** + * 工单关联多辆车 + * @param ticketName + * @param vehicleInfoDTOList + */ + void batchVehicleInsertToTicket(String ticketName, List vehicleInfoDTOList); + + /** + * 根据车辆vidList查询车辆信息 + * @param id + * @param dto + * @return + */ + List getVehicleViews(UUID id, TicketParamsDTO dto); + + /** + * + * @param ticket + * @param dto + */ + void updateGroupVinAndInfo(Ticket ticket, TicketParamsDTO dto); + + /** + * 获取工单下的车辆信息 + * @param pageable + * @return + */ + Page pageableVehicleInfo(Pageable pageable, UUID ticketId); +} diff --git a/src/main/java/com/volkswagen/mdmds/service/UserService.java b/src/main/java/com/volkswagen/mdmds/service/UserService.java new file mode 100644 index 0000000..36cd58b --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/UserService.java @@ -0,0 +1,39 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.param.RoleCreateParam; +import com.volkswagen.mdmds.model.param.UserStatusParam; +import com.volkswagen.mdmds.model.vo.RoleResourceTreeVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public interface UserService { + + UserInfoDTO initInfo(UserInfoDTO userInfoDTO); + + Page pageableUserInfos(Pageable pageable); + + void alterUserStatus(UUID id, UserStatusParam param); + + Page pageableRoleInfos(Pageable pageable); + + void deleteRoleById(UUID id); + + Page pageableResourceInfos(Pageable pageable); + + List getRoleItem(); + + List getResourceItem(); + + List getTreeItem(); + + void setRoleResource(RoleResourceDetailDTO dto); + + List> getAllResourceView(); + + void addRole(RoleCreateParam param); +} diff --git a/src/main/java/com/volkswagen/mdmds/service/VehicleService.java b/src/main/java/com/volkswagen/mdmds/service/VehicleService.java new file mode 100644 index 0000000..5d9e4dd --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/VehicleService.java @@ -0,0 +1,39 @@ +package com.volkswagen.mdmds.service; + +import com.volkswagen.mdmds.model.dto.VehicleParamsDTO; +import com.volkswagen.mdmds.model.dto.VehicleReturnDTO; + +import java.util.List; + +public interface VehicleService { + + + /** + * 根据批量vin获取vid + * @param dto + * @return + */ + List getVidList(VehicleParamsDTO dto); + + /** + * 根据批量vid获取vin + * @param dto + * @return + */ + List getVinList(VehicleParamsDTO dto); + + /** + * 根据批量vid获取车辆信息 + * @param dto + * @return + */ + List getVehicleInfoList(VehicleParamsDTO dto); + + /** + * 根据车辆字段名称获取车辆字段的数据 + * @param name + * @return + */ + String getVehicleFieldValuesByName(String name); + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/AttributeServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/AttributeServiceImpl.java new file mode 100644 index 0000000..820a562 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/AttributeServiceImpl.java @@ -0,0 +1,606 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.dto.AttrWithValuesDTO; +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.dto.UploadDataDTO; +import com.volkswagen.mdmds.model.entity.DicAttrValueEnum; +import com.volkswagen.mdmds.model.entity.DicVehicleAttr; +import com.volkswagen.mdmds.model.entity.DicVehicleAttrAdapter; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.excel.VehicleAttributeAdapterField; +import com.volkswagen.mdmds.model.excel.VehicleAttributeField; +import com.volkswagen.mdmds.model.param.DataSourceAdapterParam; +import com.volkswagen.mdmds.model.param.DataSourceParam; +import com.volkswagen.mdmds.model.vo.ExcelCheckVo; +import com.volkswagen.mdmds.repos.DicAttrValueEnumRepository; +import com.volkswagen.mdmds.repos.DicVehicleAttrAdapterRepository; +import com.volkswagen.mdmds.repos.DicVehicleAttrRepository; +import com.volkswagen.mdmds.service.AttributeService; +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.utils.AntThreadPoolUtil; +import com.volkswagen.mdmds.utils.ExcelUtil; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutionException; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@Service +public class AttributeServiceImpl implements AttributeService { + + protected Logger log = LoggerFactory.getLogger(AttributeServiceImpl.class); + + private static final String VEHICLE_FIELD_REMARK = "This attribute can not be found in DT"; + private static final String RESPONSE_ROW_NULL = "There is a null value in the row: "; + private static final String RESPONSE_DUPLICATE = "Duplicate field: "; + private static final String RESPONSE_REQUIRED = "Missing required fields: "; + private static final String ENUM_FORMAT = "%s(%s)"; + + @Autowired + private LinkDTService linkDTService; + + @PersistenceContext + private EntityManager entityManager; + + private final DicVehicleAttrRepository dicVehicleAttrRepository; + private final DicAttrValueEnumRepository dicAttrValueEnumRepository; + private final DicVehicleAttrAdapterRepository dicVehicleAttrAdapterRepository; + + public AttributeServiceImpl(DicVehicleAttrRepository dicVehicleAttrRepository, DicAttrValueEnumRepository dicAttrValueEnumRepository, DicVehicleAttrAdapterRepository dicVehicleAttrAdapterRepository) { + this.dicVehicleAttrRepository = dicVehicleAttrRepository; + this.dicAttrValueEnumRepository = dicAttrValueEnumRepository; + this.dicVehicleAttrAdapterRepository = dicVehicleAttrAdapterRepository; + } + + + @Override + public DicVehicleAttr addNewAttr(AttributeDTO attributeDTO) { + String attrName = attributeDTO.getAttrName(); + String mappingName = attributeDTO.getMappingName(); + List aList = dicVehicleAttrRepository.findByAttrName(attrName); + if(!aList.isEmpty()) { + throw new MdmdsException("Existing Attribute Name field: " + attrName, HttpStatus.CONFLICT); + } + List mList = dicVehicleAttrRepository.findByMappingName(mappingName); + if(!mList.isEmpty()) { + throw new MdmdsException("Existing Mapping Name field: " + mappingName, HttpStatus.CONFLICT); + } + // 获取DT的车辆属性字段 + JSONArray dtAttrs = getVehicleFieldFromDT(); + DicVehicleAttr dicVehicleAttr = new DicVehicleAttr(); + dicVehicleAttr.setAttrName(attrName); + if (dtAttrs.contains(attrName)) { + dicVehicleAttr.setStatus(ItemStatus.ENABLE); + } else { + dicVehicleAttr.setStatus(ItemStatus.DISABLE); + dicVehicleAttr.setRemark(VEHICLE_FIELD_REMARK); + } + dicVehicleAttr.setMappingName(attributeDTO.getMappingName()); + dicVehicleAttrRepository.save(dicVehicleAttr); + return dicVehicleAttr; + } + + @Override + public List getAllAttrs() { + List attributeDTOS = new ArrayList<>(); + Sort sort = Sort.by(Sort.Direction.ASC, "attrName"); + List dicVehicleAttrs = dicVehicleAttrRepository.findAll(sort); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + AttributeDTO attributeDTONew = new AttributeDTO(); + BeanUtils.copyProperties(dicVehicleAttr, attributeDTONew); + attributeDTOS.add(attributeDTONew); + } + return attributeDTOS; + } + + @Override + public List getAttrViews(AttributeDTO attributeDTO) { + List attributeDTOS = new ArrayList<>(); + List dicVehicleAttrs; + if (attributeDTO.getStatus() == null) { + dicVehicleAttrs = dicVehicleAttrRepository.findAll(); + } else { + dicVehicleAttrs = dicVehicleAttrRepository.findByStatus(attributeDTO.getStatus()); + + } + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + AttributeDTO attributeDTONew = new AttributeDTO(); + BeanUtils.copyProperties(dicVehicleAttr, attributeDTONew); + attributeDTOS.add(attributeDTONew); + } + return attributeDTOS; + } + + @Override + public DicVehicleAttr changeAttributeStatus(UUID id, AttributeDTO dto) { + Optional dicVehicleAttrOptional = dicVehicleAttrRepository.findById(id); + if (dicVehicleAttrOptional.isEmpty()) { + throw new MdmdsException("The vehicle attribute field does not exist", HttpStatus.CONFLICT); + } + DicVehicleAttr dicVehicleAttr = dicVehicleAttrOptional.get(); + if(dicVehicleAttr.getMappingName().equals(CommonField.ADS_VERSION_FIELD) && dto.getStatus().equals(ItemStatus.DISABLE)) { + throw new MdmdsException("Key fields cannot be set", HttpStatus.CONFLICT); + } + dicVehicleAttr.setStatus(dto.getStatus()); + dicVehicleAttrRepository.save(dicVehicleAttr); + return dicVehicleAttr; + } + + @Override + public DicVehicleAttr deleteAttributeById(UUID id) { + Optional dicVehicleAttrOptional = dicVehicleAttrRepository.findById(id); + if (dicVehicleAttrOptional.isEmpty()) { + throw new MdmdsException("车辆属性字段不存在", HttpStatus.CONFLICT); + } + DicVehicleAttr dicVehicleAttr = dicVehicleAttrOptional.get(); + dicVehicleAttrRepository.delete(dicVehicleAttr); + return dicVehicleAttr; + } + + @Override + public DicVehicleAttr updateVehicleAttr(UUID id, AttributeDTO dto) { + Optional dicVehicleAttrOptional = dicVehicleAttrRepository.findById(id); + if (dicVehicleAttrOptional.isEmpty()) { + throw new MdmdsException("vehicle key dose not exist", HttpStatus.CONFLICT); + } + DicVehicleAttr dicVehicleAttr = dicVehicleAttrOptional.get(); + dicVehicleAttr.setAttrName(dto.getAttrName()); + dicVehicleAttr.setMappingName(dto.getMappingName()); + dicVehicleAttr.setStatus(dto.getStatus()); + dicVehicleAttrRepository.save(dicVehicleAttr); + return dicVehicleAttr; + } + + @Override + public void clearTable() { + dicVehicleAttrRepository.deleteAll(); + } + + @Override + public void verification() { + // 获取DT的车辆属性字段 + JSONArray dtAttrs = getVehicleFieldFromDT(); + // 获取数据库的车辆属性字段 + List dicVehicleAttrs = dicVehicleAttrRepository.findAll(); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + if (dtAttrs.contains(dicVehicleAttr.getAttrName())) { + dicVehicleAttr.setRemark(StringUtils.EMPTY); + } else { + dicVehicleAttr.setRemark(VEHICLE_FIELD_REMARK); + } + } + dicVehicleAttrRepository.saveAll(dicVehicleAttrs); + } + + @Override + public String verificationAttrName(AttributeDTO dto) { + // 获取DT的车辆属性字段 + JSONArray dtAttrs = getVehicleFieldFromDT(); + String attrName = dto.getAttrName(); + if (!dtAttrs.contains(attrName)) { + return VEHICLE_FIELD_REMARK; + } + return StringUtils.EMPTY; + } + + @Override + public void getAttrValue() { + // 获取DT的车辆属性字段 + JSONArray dtAttrs = getVehicleFieldFromDT(); + // 获取数据库的车辆属性字段 + List dicVehicleAttrList = new ArrayList<>(); + List dicVehicleAttrs = dicVehicleAttrRepository.findAll(); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + if (dtAttrs.contains(dicVehicleAttr.getAttrName())) { + dicVehicleAttr.setRemark(StringUtils.EMPTY); + dicVehicleAttrList.add(dicVehicleAttr); + } else { + dicVehicleAttr.setRemark(VEHICLE_FIELD_REMARK); + } + } + // 根据数据库车辆属性字段获取对应的值,用于展示车型筛选条件的下拉列表 + if (!dicVehicleAttrList.isEmpty()) { + List dicAttrValueEnums = getVehicleFieldValueFromDT(dicVehicleAttrList); + if (!dicAttrValueEnums.isEmpty()) { + dicAttrValueEnumRepository.saveAll(dicAttrValueEnums); + } + } + } + + @Override + public List getAllAttrValueMap() { + List dicVehicleAttrs = dicVehicleAttrRepository.findAll(); + if (dicVehicleAttrs.isEmpty()) { + throw new MdmdsException("车辆属性字段没有数据,待确认Digital Twin接口是否存在数据同步", HttpStatus.CONFLICT); + } + Map dicAttrValueEnumMap = new HashMap<>(); + List dicAttrValueEnums = dicAttrValueEnumRepository.findAll(); + if (!dicAttrValueEnums.isEmpty()) { + dicAttrValueEnumMap = dicAttrValueEnums.stream().collect(Collectors.toMap(DicAttrValueEnum::getAttrName, Function.identity(), (key1, key2) -> key2)); + } + List attrAdapters = dicVehicleAttrAdapterRepository.findAll(); + Map mdsVersionMap = attrAdapters.stream().collect(Collectors.toMap(DicVehicleAttrAdapter::getAdapterMapping, DicVehicleAttrAdapter::getAdapterValue, (key1, key2) -> key2)); + List attrWithValuesDTOS = new ArrayList<>(); + if (!dicAttrValueEnumMap.isEmpty()) { + assembleAttrWithValuesDTOS(dicVehicleAttrs, dicAttrValueEnumMap, attrWithValuesDTOS, mdsVersionMap); + } else { + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + attrWithValuesDTOS.add(assembleAttrWithValuesDTO(dicVehicleAttr.getAttrName(), dicVehicleAttr.getMappingName())); + } + } + return attrWithValuesDTOS; + } + + private void assembleAttrWithValuesDTOS(List dicVehicleAttrs, Map dicAttrValueEnumMap + , List attrWithValuesDTOS, Map mdsVersionMap) { + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrs) { + if (dicVehicleAttr.getStatus() == null || !dicVehicleAttr.getStatus().equals(ItemStatus.ENABLE)) { + continue; + } + AttrWithValuesDTO attrWithValuesDTO = assembleAttrWithValuesDTO(dicVehicleAttr.getAttrName(), dicVehicleAttr.getMappingName()); + JSONArray attrValList = assembleAttrValList(dicAttrValueEnumMap, attrWithValuesDTO, mdsVersionMap); + if (null != attrValList && !attrValList.isEmpty()) { + attrWithValuesDTO.setValues(attrValList); + } + attrWithValuesDTOS.add(attrWithValuesDTO); + } + } + + private AttrWithValuesDTO assembleAttrWithValuesDTO(String attrName, String mappingName) { + AttrWithValuesDTO attrWithValuesDTO = new AttrWithValuesDTO(); + attrWithValuesDTO.setAttrName(attrName); + attrWithValuesDTO.setMappingName(mappingName); + return attrWithValuesDTO; + } + + private JSONArray assembleAttrValList(Map dicAttrValueEnumMap, AttrWithValuesDTO attrWithValuesDTO, Map mdsVersionMap) { + String attrName = attrWithValuesDTO.getAttrName(); + JSONArray jsonArray = new JSONArray(); + if (dicAttrValueEnumMap.containsKey(attrName)) { + DicAttrValueEnum dicAttrValueEnum = dicAttrValueEnumMap.get(attrName); + String attrVal = dicAttrValueEnum.getAttrVal(); + if (!attrVal.isEmpty()) { + List values = JSON.parseArray(attrVal, String.class); + if (CommonField.ADS_VERSION_FIELD.equals(attrWithValuesDTO.getMappingName())) { + for (Map.Entry mdsMap : mdsVersionMap.entrySet()) { + Map enumMap = new HashMap<>(1); + enumMap.put(mdsMap.getKey(), mdsMap.getValue()); + jsonArray.add(enumMap); + } + } else { + for (String value : values) { + Map enumMap = new HashMap<>(1); + enumMap.put(value, value); + jsonArray.add(enumMap); + } + } + } + } + return jsonArray; + } + + @Transactional + @Override + public void uploadAttributeFiled(MultipartFile file) { + List vehicleAttributeFieldList = ExcelUtil.readFile(file, VehicleAttributeField.class); + // 封装导入的车辆字段数据 + List baseFieldList = new ArrayList<>(CommonField.VEHICLE_BASE_FIELDS); + List uploadFieldAttrList = new ArrayList<>(); + List uploadFieldMappingList = new ArrayList<>(); + List dicVehicleAttrList = new ArrayList<>(); + assembleCheckedOld(vehicleAttributeFieldList, dicVehicleAttrList, uploadFieldAttrList, uploadFieldMappingList); + baseFieldList.removeAll(uploadFieldAttrList); + if(!baseFieldList.isEmpty()) { + throw new MdmdsException(RESPONSE_REQUIRED + StringUtils.join(baseFieldList, ","), HttpStatus.CONFLICT); + } + // 从DT获取所有车辆字段数据 + JSONArray dtAttrs = getVehicleFieldFromDT(); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrList) { + if (dtAttrs.contains(dicVehicleAttr.getAttrName())) { + dicVehicleAttr.setStatus(ItemStatus.ENABLE); + dicVehicleAttr.setRemark(StringUtils.EMPTY); + } else { + dicVehicleAttr.setStatus(ItemStatus.DISABLE); + dicVehicleAttr.setRemark(VEHICLE_FIELD_REMARK); + } + } + if (!dicVehicleAttrList.isEmpty()) { + // 删除属于车辆属性字段数据 + dicVehicleAttrRepository.deleteAll(); + dicAttrValueEnumRepository.deleteAll(); + dicVehicleAttrRepository.saveAll(dicVehicleAttrList); + List dicAttrValueEnums = getVehicleFieldValueFromDT(dicVehicleAttrList); + if (!dicAttrValueEnums.isEmpty()) { + dicAttrValueEnumRepository.saveAll(dicAttrValueEnums); + } + } + } + + private void assembleCheckedOld(List vehicleAttributeFieldList, List dicVehicleAttrList, List uploadFieldAttrList, List uploadFieldMappingList) { + int i = 1; + for (VehicleAttributeField dataSourceParam : vehicleAttributeFieldList) { + i++; + String attrName = dataSourceParam.getAttrName(); + String mappingName = dataSourceParam.getMappingName(); + if(attrName.isEmpty() || attrName.isBlank() || mappingName.isEmpty() || mappingName.isBlank()) { + throw new MdmdsException(RESPONSE_ROW_NULL + i, HttpStatus.CONFLICT); + } + if(uploadFieldAttrList.contains(attrName)) { + throw new MdmdsException(RESPONSE_DUPLICATE + attrName, HttpStatus.CONFLICT); + } + if(uploadFieldMappingList.contains(mappingName)) { + throw new MdmdsException(RESPONSE_DUPLICATE + mappingName, HttpStatus.CONFLICT); + } + uploadFieldAttrList.add(attrName); + uploadFieldMappingList.add(mappingName); + DicVehicleAttr dicVehicleAttr = new DicVehicleAttr(); + dicVehicleAttr.setAttrName(attrName); + dicVehicleAttr.setMappingName(mappingName); + dicVehicleAttrList.add(dicVehicleAttr); + } + } + + @Override + public ResponseEntity uploadAttributeFieldCheckData(MultipartFile file) { + String originalFileName = file.getOriginalFilename(); + if(originalFileName != null && !originalFileName.contains(".xlsx")) { + throw new MdmdsException("File type error", HttpStatus.CONFLICT); + } + ExcelCheckVo excelCheckVo = new ExcelCheckVo(); + List vehicleAttributeFieldList = ExcelUtil.readFile(file, VehicleAttributeField.class); + // 封装导入的车辆字段数据 + List baseFieldList = new ArrayList<>(CommonField.VEHICLE_BASE_FIELDS); + List uploadFieldAttrList = new ArrayList<>(); + List uploadFieldMappingList = new ArrayList<>(); + List dicVehicleAttrList = new ArrayList<>(); + assembleCheckedOld(vehicleAttributeFieldList, dicVehicleAttrList, uploadFieldAttrList, uploadFieldMappingList); + baseFieldList.removeAll(uploadFieldMappingList); + if(!baseFieldList.isEmpty()) { + throw new MdmdsException(RESPONSE_REQUIRED + StringUtils.join(baseFieldList, ","), HttpStatus.CONFLICT); + } + List adapterFields = ExcelUtil.readFile(file, VehicleAttributeAdapterField.class, 1); + if (!adapterFields.isEmpty()) { + Map> mappingNameMap = adapterFields.stream().collect(Collectors.groupingBy(VehicleAttributeAdapterField::getAttrName)); + for (Map.Entry> adapterEntry : mappingNameMap.entrySet()) { + boolean containsMappingName = vehicleAttributeFieldList.stream().anyMatch(attributeField -> attributeField.getAttrName().equals(adapterEntry.getKey())); + if (!containsMappingName) { + throw new MdmdsException(RESPONSE_REQUIRED + adapterEntry.getKey() + " in Attribute Name", HttpStatus.CONFLICT); + } + } + } + List dataSourceAdapterVos = new ArrayList<>(); + for(VehicleAttributeAdapterField vehicleAttributeField : adapterFields) { + ExcelCheckVo.DataSourceAdapterVo dataSourceAdapterVo = new ExcelCheckVo.DataSourceAdapterVo(); + dataSourceAdapterVo.setAttrName(vehicleAttributeField.getAttrName()); + dataSourceAdapterVo.setAdapterKey(vehicleAttributeField.getAdapterKey()); + dataSourceAdapterVo.setAdapterValue(vehicleAttributeField.getAdapterValue()); + dataSourceAdapterVos.add(dataSourceAdapterVo); + } + excelCheckVo.setAdapterlist(dataSourceAdapterVos); + + List dataSourceVoList = new ArrayList<>(); + for(VehicleAttributeField vehicleAttributeField : vehicleAttributeFieldList) { + ExcelCheckVo.DataSourceVo dataSourceVo = new ExcelCheckVo.DataSourceVo(); + dataSourceVo.setAttrName(vehicleAttributeField.getAttrName()); + dataSourceVo.setMappingName(vehicleAttributeField.getMappingName()); + dataSourceVoList.add(dataSourceVo); + } + excelCheckVo.setList(dataSourceVoList); + + StringBuilder sb = new StringBuilder(); + List vehicleKeyList = dicVehicleAttrRepository.findAll(); + Map attrToMapDB = vehicleKeyList.stream().collect(Collectors.toMap(DicVehicleAttr::getAttrName, DicVehicleAttr::getMappingName)); + Map attrToMapExcel = vehicleAttributeFieldList.stream().collect(Collectors.toMap(VehicleAttributeField::getAttrName, VehicleAttributeField::getMappingName)); + for(Map.Entry entry : attrToMapDB.entrySet()) { + if(!attrToMapExcel.containsKey(entry.getKey())) { + // 准备删除的attrName + sb.append(entry.getKey()).append(","); + } + } + if(!sb.isEmpty()) { + sb.insert(0, "About to overwrite deleted data fields: "); + sb.deleteCharAt(sb.length() - 1); + excelCheckVo.setMessage(sb.toString()); + } + return ResponseEntity.ok(excelCheckVo); + } + + @Transactional + @Override + public void uploadAttribute(UploadDataDTO uploadDataDTO) { + List params = uploadDataDTO.getList(); + Map enumValueMap = new HashMap<>(8); + // 封装导入的车辆字段数据 + List baseFieldList = new ArrayList<>(CommonField.VEHICLE_BASE_FIELDS); + List uploadFieldAttrList = new ArrayList<>(); + List uploadFieldMappingList = new ArrayList<>(); + List dicVehicleAttrList = new ArrayList<>(); + assembleChecked(params, dicVehicleAttrList, uploadFieldAttrList, uploadFieldMappingList); + baseFieldList.removeAll(uploadFieldMappingList); + if(!baseFieldList.isEmpty()) { + throw new MdmdsException(RESPONSE_REQUIRED + StringUtils.join(baseFieldList, ","), HttpStatus.CONFLICT); + } + + List attrAdapters = new ArrayList<>(); + if (!uploadDataDTO.getAdapterlist().isEmpty()) { + Map> mappingNameMap = uploadDataDTO.getAdapterlist().stream() + .collect(Collectors.groupingBy(DataSourceAdapterParam::getAttrName)); + for (Map.Entry> adapterEntry : mappingNameMap.entrySet()) { + boolean containsMappingName = params.stream().anyMatch(attributeField -> attributeField.getAttrName().equals(adapterEntry.getKey())); + if (!containsMappingName) { + throw new MdmdsException(RESPONSE_REQUIRED + adapterEntry.getKey() + " in Attribute Name", HttpStatus.CONFLICT); + } + JSONArray jsonArray = new JSONArray(); + Date nowDate = new Date(); + for (DataSourceAdapterParam dataSourceAdapterParam : adapterEntry.getValue()) { + Map enumMap = new HashMap<>(32); + String mappingKey = String.format(ENUM_FORMAT, dataSourceAdapterParam.getAdapterKey(), dataSourceAdapterParam.getAdapterValue()); + enumMap.put(mappingKey, dataSourceAdapterParam.getAdapterValue()); + jsonArray.add(enumMap); + + DicVehicleAttrAdapter dicVehicleAttrAdapter = new DicVehicleAttrAdapter(); + dicVehicleAttrAdapter.setId(UUID.randomUUID()); + dicVehicleAttrAdapter.setCreateBy("SYS"); + dicVehicleAttrAdapter.setCreationDate(nowDate); + dicVehicleAttrAdapter.setAttrName(dataSourceAdapterParam.getAttrName()); + dicVehicleAttrAdapter.setAdapterMapping(mappingKey); + dicVehicleAttrAdapter.setAdapterKey(dataSourceAdapterParam.getAdapterKey()); + dicVehicleAttrAdapter.setAdapterValue(dataSourceAdapterParam.getAdapterValue()); + attrAdapters.add(dicVehicleAttrAdapter); + } + enumValueMap.put(adapterEntry.getKey(), jsonArray.toJSONString()); + } + } + + // 从DT获取所有车辆字段数据 + JSONArray dtAttrs = getVehicleFieldFromDT(); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrList) { + if (dtAttrs.contains(dicVehicleAttr.getAttrName())) { + dicVehicleAttr.setStatus(ItemStatus.ENABLE); + dicVehicleAttr.setRemark(StringUtils.EMPTY); + } else { + dicVehicleAttr.setStatus(ItemStatus.DISABLE); + dicVehicleAttr.setRemark(VEHICLE_FIELD_REMARK); + } + } + if (!dicVehicleAttrList.isEmpty()) { + // 删除属于车辆属性字段数据 + dicVehicleAttrRepository.deleteAll(); + dicAttrValueEnumRepository.deleteAll(); + dicVehicleAttrRepository.saveAll(dicVehicleAttrList); + List dicAttrValueEnums = getVehicleFieldValueFromDT(dicVehicleAttrList); + if (!dicAttrValueEnums.isEmpty()) { + dicAttrValueEnumRepository.saveAll(dicAttrValueEnums); + } + if (!attrAdapters.isEmpty()) { + attrAdapters.forEach(dicVehicleAttrAdapterRepository::saveIgnoreConflict); + } + } + } + + private void assembleChecked(List params, List dicVehicleAttrList, List uploadFieldAttrList, List uploadFieldMappingList) { + int i = 1; + for (DataSourceParam dataSourceParam : params) { + i++; + String attrName = dataSourceParam.getAttrName(); + String mappingName = dataSourceParam.getMappingName(); + if(attrName.isEmpty() || attrName.isBlank() || mappingName.isEmpty() || mappingName.isBlank()) { + throw new MdmdsException(RESPONSE_ROW_NULL + i, HttpStatus.CONFLICT); + } + if(uploadFieldAttrList.contains(attrName)) { + throw new MdmdsException(RESPONSE_DUPLICATE + attrName, HttpStatus.CONFLICT); + } + if(uploadFieldMappingList.contains(mappingName)) { + throw new MdmdsException(RESPONSE_DUPLICATE + mappingName, HttpStatus.CONFLICT); + } + uploadFieldAttrList.add(attrName); + uploadFieldMappingList.add(mappingName); + DicVehicleAttr dicVehicleAttr = new DicVehicleAttr(); + dicVehicleAttr.setAttrName(attrName); + dicVehicleAttr.setMappingName(mappingName); + dicVehicleAttrList.add(dicVehicleAttr); + } + } + + @Transactional + @Override + public void syncVehicleKeyAndValue() { + // 从数据库查询需要同步更新的字段 + List vehicleKeyList = dicVehicleAttrRepository.findAll(); + // 从DT查询vehicle的key + JSONArray vehicleKeyListFromDT = getVehicleFieldFromDT(); + for(DicVehicleAttr vehicleKey : vehicleKeyList) { + if(vehicleKeyListFromDT.contains(vehicleKey.getAttrName())) { + vehicleKey.setRemark(StringUtils.EMPTY); + } else { + vehicleKey.setRemark(VEHICLE_FIELD_REMARK); + } + } + // 从DT查询vehicle的value + if(!vehicleKeyList.isEmpty()) { + Long sTime = System.currentTimeMillis(); + List vehicleValueListFromDT = getVehicleFieldValueFromDT(vehicleKeyList); + log.info("DT interface concurrent call(/state-api/vehicles/state/values) consumeTime={}", System.currentTimeMillis() - sTime); + if(!vehicleValueListFromDT.isEmpty()) { + dicAttrValueEnumRepository.deleteAll(); + dicAttrValueEnumRepository.saveAll(vehicleValueListFromDT); + } + } + // 同步更新Vehicle Key + dicVehicleAttrRepository.saveAll(vehicleKeyList); + } + + private JSONArray getVehicleFieldFromDT() { + try { + Object result = linkDTService.getAllAttributes(); + return JSON.parseArray(result.toString()); + } catch (IOException | NoSuchAlgorithmException | KeyManagementException | ExecutionException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + private List getVehicleFieldValueFromDT(List dicVehicleAttrList) { + List dicAttrValueEnums = new CopyOnWriteArrayList<>(); + try { + List> initThreads = new ArrayList<>(); + for (DicVehicleAttr dicVehicleAttr : dicVehicleAttrList) { + String attrName = dicVehicleAttr.getAttrName(); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("key", attrName); + Callable callable = () -> { + Object result = linkDTService.getAllEnumForAttribute(params); + JSONArray dtAttrsValues = JSON.parseArray(result.toString()); + DicAttrValueEnum dicAttrValueEnum = new DicAttrValueEnum(); + JSONArray dbAttrsValues = new JSONArray(); + for (int idx = 0; idx < dtAttrsValues.size(); idx++) { + String attrValue = dtAttrsValues.getString(idx); + if (attrValue != null) { + dbAttrsValues.add(attrValue); + } + } + dicAttrValueEnum.setAttrName(attrName); + dicAttrValueEnum.setAttrVal(dbAttrsValues.toJSONString()); + dicAttrValueEnums.add(dicAttrValueEnum); + return true; + }; + initThreads.add(callable); + } + AntThreadPoolUtil.addThread(initThreads); + return dicAttrValueEnums; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new MdmdsException("DT interface concurrent call(/state-api/vehicles/state/values) error:" + e.getMessage(), HttpStatus.CONFLICT); + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/AuditServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/AuditServiceImpl.java new file mode 100644 index 0000000..5844d5c --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/AuditServiceImpl.java @@ -0,0 +1,40 @@ +package com.volkswagen.mdmds.service.impl; + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.model.dto.AuditDTO; +import com.volkswagen.mdmds.model.entity.AuditLog; +import com.volkswagen.mdmds.repos.AuditLogRepository; +import com.volkswagen.mdmds.service.AuditService; +import org.springframework.beans.BeanUtils; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Service +public class AuditServiceImpl implements AuditService { + + private final AuditLogRepository auditLogRepository; + + public AuditServiceImpl(AuditLogRepository auditLogRepository) { + this.auditLogRepository = auditLogRepository; + } + + @Override + public void insertOne(AuditDTO auditDTO) { + AuditLog auditLog = new AuditLog(); + BeanUtils.copyProperties(auditDTO, auditLog); + auditLogRepository.save(auditLog); + } + + @Override + public int countByCondition(String id) { + int countRes=-1; + try{ + countRes = auditLogRepository.countById(UUID.randomUUID()); + }catch (Exception ex){ + throw new MdmdsException("DB Error", HttpStatus.SERVICE_UNAVAILABLE); + } + return countRes; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/GroupServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/GroupServiceImpl.java new file mode 100644 index 0000000..a12123e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/GroupServiceImpl.java @@ -0,0 +1,655 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.*; +import com.volkswagen.mdmds.model.param.VehicleGroupParam; +import com.volkswagen.mdmds.model.pojo.GroupVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.VehicleGroupVo; +import com.volkswagen.mdmds.repos.*; +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.service.GroupService; +import com.volkswagen.mdmds.service.VehicleService; +import com.volkswagen.mdmds.utils.AntStrUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.modelmapper.internal.util.CopyOnWriteLinkedHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.http.HttpStatus; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +/** + * @author Shuo Ding + * @since 2023/3/16 + */ +@Service +public class GroupServiceImpl implements GroupService { + + protected Logger log = LoggerFactory.getLogger(GroupServiceImpl.class); + + private static final String VEHICLE_GROUP_NO = "Vehicle group does not exist"; + private static final String RES_VEHICLE_LIST = "vehicleList"; + private static final String RES_VEHICLE_VALUE = "value"; + + @Resource + private LinkDTService linkDTService; + + @Resource + private VehicleService vehicleService; + + //分组表的操作对象 + private final VehicleGroupRepository vehicleGroupRepository; + + //分组条件的操作对象 + private final GroupSpecificationRepository groupSpecRepository; + + private final GroupVehicleRepository groupVehicleRepository; + + private final DataCollectionConfigRepository dataCollectionConfigRepository; + private final GroupConfigurationRepository groupConfigurationRepository; + private final GroupDccRecordRepository groupDccRecordRepository; + + public GroupServiceImpl(VehicleGroupRepository vehicleGroupRepository, GroupSpecificationRepository groupSpecRepository, + GroupVehicleRepository groupVehicleRepository, DataCollectionConfigRepository dataCollectionConfigRepository, GroupConfigurationRepository groupConfigurationRepository, GroupDccRecordRepository groupDccRecordRepository) { + this.vehicleGroupRepository = vehicleGroupRepository; + this.groupSpecRepository = groupSpecRepository; + this.groupVehicleRepository = groupVehicleRepository; + this.dataCollectionConfigRepository = dataCollectionConfigRepository; + this.groupConfigurationRepository = groupConfigurationRepository; + this.groupDccRecordRepository = groupDccRecordRepository; + } + + @Override + @Modifying + @Transactional + public UUID createNewGroupByName(String groupName) { + List list = vehicleGroupRepository.findAllByGroupNameEqualsAndIsDeleted(groupName, 0); + if(!list.isEmpty()) { + throw new MdmdsException("Group name already exists", HttpStatus.CONFLICT); + } + VehicleGroup vehicleGroup = new VehicleGroup(); + vehicleGroup.setGroupName(groupName); + vehicleGroup.setStatus(ItemStatus.NONE); + vehicleGroup.setIsDeleted(0); + vehicleGroup.setMold(0); + vehicleGroup.setTotal(0); + VehicleGroup group = vehicleGroupRepository.save(vehicleGroup); + return group.getId(); + } + + @Override + @Modifying + @Transactional + public VehicleGroup updateGroupSpecInfo(GroupDetailInfoDTO dto) { + //dto里必须有id + Optional vehicleGroupOptional = vehicleGroupRepository.findById(dto.getId()); + + if (vehicleGroupOptional.isPresent()) { + VehicleGroup vehicleGroup = vehicleGroupOptional.get(); + // 分组关联车辆查询条件和标签(每个分组可以设置"事故车","G50高速"等标签) + GroupSpecification groupSpecification = vehicleGroup.getGroupSpecification(); + checkedCondition(dto, groupSpecification); + if(groupSpecification == null) { + groupSpecification = new GroupSpecification(); + } + groupSpecification.setSpecificationJson(dto.getSpecificationJson()); + groupSpecification.setTags(assembleTags(dto)); + + groupSpecRepository.save(groupSpecification); + vehicleGroup.setGroupSpecification(groupSpecification); + // 分组关联车辆VIN和VID + // *根据条件获取DT所有车辆ID + Object result; + try { + result = linkDTService.getVehicleIdByCondition(dto.getSpecificationJson()); + } catch (IOException | ExecutionException | NoSuchAlgorithmException | KeyManagementException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.CONFLICT); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ex.getMessage(), HttpStatus.CONFLICT); + } + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + JSONArray vidJSONArray = vidJSONObject.getJSONArray(RES_VEHICLE_LIST); + // *获取DT所有车辆ID,更新分组与车辆ID的关联关系 + List groupVehicles = assembleGroupVehicleList(vidJSONArray, dto.getId()); + if(!groupVehicles.isEmpty()) { + groupVehicleRepository.saveAll(groupVehicles); + } + vehicleGroup.setMold(1);// 分组创建关联VID(按车辆字段条件查询获取VID) + return vehicleGroupRepository.save(vehicleGroup); + } else { + throw new MdmdsException("未知分组,不可更新", HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + private void checkedCondition(GroupDetailInfoDTO dto, GroupSpecification groupSpecificationDb) { + if (groupSpecificationDb != null && groupSpecificationDb.isContainSpec()) { + throw new MdmdsException("分组条件已经被锁定,不可更新", HttpStatus.LOCKED); + } + if(null == dto.getSpecificationJson() || dto.getSpecificationJson().length() == 0) { + throw new MdmdsException("车辆查询条件必填", HttpStatus.LOCKED); + } + } + + private String assembleTags(GroupDetailInfoDTO dto) { + if(null != dto.getTags() && !dto.getTags().isEmpty()) { + return dto.getTags().stream().collect(Collectors.joining(";")); + } else { + return ""; + } + } + + private List assembleGroupVehicleList(JSONArray vidJSONArray, UUID groupId) { + List groupVehicles = new ArrayList<>(); + for(int idx = 0; idx < vidJSONArray.size(); idx++) { + GroupVehicle groupVehicle = new GroupVehicle(); + groupVehicle.setGroupId(groupId); + String vid = vidJSONArray.getString(idx); + groupVehicle.setVid(vid); + groupVehicles.add(groupVehicle); + } + return groupVehicles; + } + + @Async + @Override + @Modifying + @Transactional + public void updateGroupVehicleByCriteria(List vidList, VehicleGroup vehicleGroup, GroupDetailInfoDTO dto) { +// vehicleGroup.setMold(1);// 分组创建关联VID(按车辆字段条件查询获取VID) + vehicleGroup.setStatus(ItemStatus.ENABLE); + + // 分组关联车辆VIN和VID + // *根据条件获取DT所有车辆ID + // *获取DT所有车辆ID,更新分组与车辆ID的关联关系 + List groupVehicles = new ArrayList<>(); + List> vidPartitionList = Lists.partition(vidList, 10); + List failList = new ArrayList<>(); + Map succMap = new HashMap<>(); + for(List vidItemList : vidPartitionList) { + // 根据VID获取VIN + VehicleParamsDTO vehicleParamsDTO = VehicleParamsDTO.builder().vidList(vidItemList).build(); + extractVidFromVW(vehicleParamsDTO, failList, succMap); + if(!failList.isEmpty()) { + break; + } + // 根据VID获取ADS Version + extractVersionFromDT(vehicleParamsDTO, failList, succMap); + if(!failList.isEmpty()) { + break; + } + } + List targetList = new ArrayList<>(); + if(!succMap.isEmpty()) { + targetList = succMap.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList()); + } + if(!failList.isEmpty()) { + vehicleGroup.setStatus(ItemStatus.DISABLE); + targetList.addAll(failList); + } + vehicleGroup.setTotal(targetList.size()); + for(VehicleReturnDTO vehicleReturnDTO : targetList) { + GroupVehicle groupVehicle = new GroupVehicle(); + groupVehicle.setGroupId(dto.getId()); + BeanUtils.copyProperties(vehicleReturnDTO, groupVehicle); + groupVehicles.add(groupVehicle); + } + if(!groupVehicles.isEmpty()) { + groupVehicleRepository.saveAll(groupVehicles); + } + vehicleGroupRepository.save(vehicleGroup); + } + + private void extractVersionFromDT(VehicleParamsDTO vehicleParamsDTO, List failList, Map succMap) { + List vehicleReturnDTOList = vehicleService.getVehicleInfoList(vehicleParamsDTO); + for(VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOList) { + if(null != vehicleReturnDTO.getStatusCode()) { + failList.add(vehicleReturnDTO); + break; + } + String vid = vehicleReturnDTO.getVid(); + if(succMap.containsKey(vid)) { + VehicleReturnDTO returnDTO = succMap.get(vid); + returnDTO.setInfos(vehicleReturnDTO.getInfos()); + returnDTO.setResult(vehicleReturnDTO.getResult()); + } + } + } + + private void extractVidFromVW(VehicleParamsDTO vehicleParamsDTO, List failList, Map succMap) { + List vehicleReturnDTOList = vehicleService.getVinList(vehicleParamsDTO); + for(VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOList) { + if(null != vehicleReturnDTO.getStatusCode()) { + failList.add(vehicleReturnDTO); + break; + } + String vid = vehicleReturnDTO.getVid(); + succMap.put(vid, vehicleReturnDTO); + } + } + + @Async + @Override + @Modifying + @Transactional + public void updateGroupVehicleByVIN(VehicleGroup vehicleGroup, GroupParamsDTO dto) { +// vehicleGroup.setMold(2);// 分组创建关联VID(按车辆VIN查询获取VID) + vehicleGroup.setStatus(ItemStatus.ENABLE); + // 根据VIN获取VID + String version = dto.getVersion(); + List vinList = dto.getVinList(); + List> vinPartitionList = Lists.partition(vinList, 10); + List failList = new ArrayList<>(); + List targetList = new ArrayList<>(); + for(List vinItemList : vinPartitionList) { + Map succItemMap = new HashMap<>(); + List vidItemList = new ArrayList<>(); + VehicleParamsDTO vehicleParamsDTO = VehicleParamsDTO.builder().vinList(vinItemList).build(); + // 根据VIN从VW.AC获取VID,若VID获取失败反馈错误信息 + extractVidFromVW(vehicleParamsDTO, failList, succItemMap, vidItemList); + // -- 根据VIN从VW.AC获取VID,若获取失败,中断更新错误信息 + if(!failList.isEmpty()) { + break; + } + // 根据VIN从DT获取ADS Version,若获取失败或者获取的ADS Version和入参不同,中断更新错误信息 + vehicleParamsDTO = VehicleParamsDTO.builder().vidList(vidItemList).build(); + extractVersionFromDT(vehicleParamsDTO, failList, succItemMap, targetList, version); + if(!failList.isEmpty()) { + break; + } + } + if(!failList.isEmpty()) { + vehicleGroup.setStatus(ItemStatus.DISABLE); + targetList.addAll(failList); + } + vehicleGroup.setTotal(targetList.size()); + List groupVehicles = assembleGroupVehicles(targetList, vehicleGroup.getId()); + if(!groupVehicles.isEmpty()) { + groupVehicleRepository.saveAll(groupVehicles); + } + vehicleGroupRepository.save(vehicleGroup); + } + + private void extractVersionFromDT(VehicleParamsDTO vehicleParamsDTO, List failList, Map succItemMap, List targetList, String version) { + List vehicleReturnDTOList = vehicleService.getVehicleInfoList(vehicleParamsDTO); + for(VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOList) { + String vid = vehicleReturnDTO.getVid(); + vehicleReturnDTO.setVin(succItemMap.get(vid)); + if(null != vehicleReturnDTO.getStatusCode()) { + failList.add(vehicleReturnDTO); + break; + } + String infos = vehicleReturnDTO.getInfos(); + if(!AntStrUtil.isJSONObject(infos)) { + failList.add(vehicleReturnDTO); + break; + } else { + JSONObject infoJSONObject = JSON.parseObject(infos); + if(!infoJSONObject.containsKey("ads_version")) { + vehicleReturnDTO.setMessage("The vehicle(vid:" + vid + ") dose not have ADS Version"); + failList.add(vehicleReturnDTO); + break; + } + String adsVersion = infoJSONObject.getString("ads_version"); + if(!version.equals(adsVersion)) { + vehicleReturnDTO.setMessage("The vehicle(vid:" + vid + ")'s ADS Version(" + adsVersion + ") is different from '" + version + "'"); + failList.add(vehicleReturnDTO); + break; + } else { + vehicleReturnDTO.setVin(succItemMap.get(vid)); + targetList.add(vehicleReturnDTO); + } + } + } + } + + private void extractVidFromVW(VehicleParamsDTO vehicleParamsDTO, List failList, Map succItemMap, List vidItemList) { + List vehicleReturnDTOVidList = vehicleService.getVidList(vehicleParamsDTO); + for(VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOVidList) { + if(null != vehicleReturnDTO.getStatusCode()) { + failList.add(vehicleReturnDTO); + break; + } + String vid = vehicleReturnDTO.getVid(); + succItemMap.put(vid, vehicleReturnDTO.getVin()); + vidItemList.add(vid); + } + } + + private List assembleGroupVehicles(List targetList, UUID groupId) { + List groupVehicles = new ArrayList<>(); + for(VehicleReturnDTO vehicleReturnDTO : targetList) { + GroupVehicle groupVehicle = new GroupVehicle(); + groupVehicle.setGroupId(groupId); + BeanUtils.copyProperties(vehicleReturnDTO, groupVehicle); + groupVehicles.add(groupVehicle); + } + return groupVehicles; + } + + @Override + @Modifying + @Transactional + public VehicleGroup updateGroupVinAndInfo(GroupDetailInfoDTO dto) { + Optional vehicleGroupOptional = vehicleGroupRepository.findById(dto.getId()); + if (vehicleGroupOptional.isPresent()) { + VehicleGroup vehicleGroup = vehicleGroupOptional.get(); + // 分组关联标签(每个分组可以设置"事故车","G50高速"等标签) + GroupSpecification groupSpecification = vehicleGroup.getGroupSpecification(); + if (groupSpecification != null && groupSpecification.isContainSpec()) { + throw new MdmdsException("分组条件已经被锁定,不可更新", HttpStatus.LOCKED); + } + if(groupSpecification == null) { + groupSpecification = new GroupSpecification(); + } + if(null != dto.getTags() && !dto.getTags().isEmpty()) { + groupSpecification.setTags(dto.getTags().stream().collect(Collectors.joining(";"))); + } else { + groupSpecification.setTags(""); + } + groupSpecRepository.save(groupSpecification); + vehicleGroup.setGroupSpecification(groupSpecification); + // 分组关联车辆VIN和VID + List vehicleInfoDTOList = dto.getVehicles(); + vehicleGroup.setMold(2);// 分组创建关联VID(按车辆VIN查询获取VID) + List groupVehicles = new ArrayList<>(); + + for(VehicleInfoDTO vehicleInfoDTO : vehicleInfoDTOList) { + GroupVehicle groupVehicle = new GroupVehicle(); + groupVehicle.setGroupId(dto.getId()); + groupVehicle.setVin(vehicleInfoDTO.getVin()); + groupVehicle.setVid(vehicleInfoDTO.getVid()); + groupVehicles.add(groupVehicle); + } + if(!groupVehicles.isEmpty()) { + groupVehicleRepository.saveAll(groupVehicles); + } + return vehicleGroupRepository.save(vehicleGroup); + } else { + throw new MdmdsException("未知分组,不可更新", HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + @Modifying + @Transactional + public void updateGroupConfiguration(UUID groupId, UUID dccId) { + Optional optionalDataCollectionConfig = dataCollectionConfigRepository.findById(dccId); + if(optionalDataCollectionConfig.isEmpty()) { + throw new MdmdsException("Configuration does not exist", HttpStatus.NOT_FOUND); + } + VehicleGroup vehicleGroupOptional = vehicleGroupRepository.findOneByIdAndIsDeleted(groupId, 0); + if(null == vehicleGroupOptional) { + throw new MdmdsException(VEHICLE_GROUP_NO, HttpStatus.NOT_FOUND); + } + Optional groupConfigurationOptional = groupConfigurationRepository.findByGroupId(groupId); + if(groupConfigurationOptional.isPresent()) { + GroupConfiguration groupConfiguration = groupConfigurationOptional.get(); + groupConfiguration.setDccId(dccId); + groupConfigurationRepository.save(groupConfiguration); + } else { + GroupConfiguration groupConfiguration = new GroupConfiguration(); + groupConfiguration.setGroupId(groupId); + groupConfiguration.setDccId(dccId); + groupConfigurationRepository.save(groupConfiguration); + } + GroupDccRecord groupDccRecord = new GroupDccRecord(); + groupDccRecord.setGroupId(groupId); + groupDccRecord.setDccId(dccId); + groupDccRecordRepository.save(groupDccRecord); + } + + @Override + @Transactional + public void unbindGroupConfiguration(UUID groupId) { + VehicleGroup vehicleGroupOptional = vehicleGroupRepository.findOneByIdAndIsDeleted(groupId, 0); + if(null == vehicleGroupOptional) { + throw new MdmdsException(VEHICLE_GROUP_NO, HttpStatus.NOT_FOUND); + } + Optional groupConfigurationOptional = groupConfigurationRepository.findByGroupId(groupId); + if(groupConfigurationOptional.isEmpty()) { + throw new MdmdsException("Group has not configuration", HttpStatus.NOT_FOUND); + } + groupConfigurationRepository.delete(groupConfigurationOptional.get()); + GroupDccRecord groupDccRecord = new GroupDccRecord(); + groupDccRecord.setGroupId(groupId); + groupDccRecordRepository.save(groupDccRecord); + } + + @Override + public Page pageableBriefGroup(Pageable pageable) { + Page groupBriefInfoDTOS = vehicleGroupRepository.findAllGroupPageable(pageable); + for(GroupReturnDTO groupReturnDTO : groupBriefInfoDTOS.getContent()) { + this.assembleStatusDes(groupReturnDTO); + } + return groupBriefInfoDTOS; + } + @Override + public Page pageableGroup(int pageNo, int pageSize, VehicleGroupParam param) { + Pageable pageable = PageRequest.of(pageNo - 1, pageSize); + if(param.getStatus().equals(ItemStatus.ALL)) { + param.setStatus(null); + } + if((!param.getTotalMin().isEmpty() && !StringUtils.isNumeric(param.getTotalMin())) || + (!param.getTotalMax().isEmpty() && !StringUtils.isNumeric(param.getTotalMax()))) { + throw new MdmdsException("Unreasonable transmission of parameters", HttpStatus.UNPROCESSABLE_ENTITY); + } + Page vehicleGroupVoPage = vehicleGroupRepository.findAllVehicleGroupPageable(pageable, param); + for(VehicleGroupVo groupReturnDTO : vehicleGroupVoPage.getContent()) { + this.assembleStatusDes(groupReturnDTO); + } + return vehicleGroupVoPage; + } + private void assembleStatusDes(VehicleGroupVo groupReturnDTO) { + if(groupReturnDTO.getStatus().equals(ItemStatus.NONE)) { + groupReturnDTO.setStatusDes("Group has no associated vehicles"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.RUN)) { + groupReturnDTO.setStatusDes("Group is associating vehicles"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.DISABLE)) { + groupReturnDTO.setStatusDes("Group associated vehicle exception"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.ENABLE)) { + groupReturnDTO.setStatusDes("Group associated vehicle successfully"); + } + } + private void assembleStatusDes(GroupReturnDTO groupReturnDTO) { + if(groupReturnDTO.getStatus().equals(ItemStatus.NONE)) { + groupReturnDTO.setStatusDes("Group has no associated vehicles"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.RUN)) { + groupReturnDTO.setStatusDes("Group is associating vehicles"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.DISABLE)) { + groupReturnDTO.setStatusDes("Group associated vehicle exception"); + } else if(groupReturnDTO.getStatus().equals(ItemStatus.ENABLE)) { + groupReturnDTO.setStatusDes("Group associated vehicle successfully"); + } + } + + @Override + public VehicleGroup deleteGroupById(UUID id) { + Optional vehicleGroupOptional = vehicleGroupRepository.findById(id); + if(vehicleGroupOptional.isEmpty()) { + throw new MdmdsException("分组不存在", HttpStatus.CONFLICT); + } + VehicleGroup vehicleGroup = vehicleGroupOptional.get(); + vehicleGroup.setIsDeleted(1); + vehicleGroupRepository.save(vehicleGroup); + return vehicleGroupOptional.get(); + } + + @Override + public void deletedGroupByIds(List idList) { + List vehicleGroupList = vehicleGroupRepository.findAllByIdInAndIsDeleted(idList, 0); + vehicleGroupList.stream().forEach(vehicleGroup -> vehicleGroup.setIsDeleted(1)); + vehicleGroupRepository.saveAll(vehicleGroupList); + } + + @Override + public GroupDetailInfoDTO getGroupDetailInfo(UUID id) { + VehicleGroup vehicleGroup = vehicleGroupRepository.findOneByIdAndIsDeleted(id, 0); + if(null == vehicleGroup) { + throw new MdmdsException(VEHICLE_GROUP_NO, HttpStatus.NOT_FOUND); + } + GroupDetailInfoDTO groupDetailInfoDTO = new GroupDetailInfoDTO(); + BeanUtils.copyProperties(vehicleGroup, groupDetailInfoDTO); + groupDetailInfoDTO.setCreateBy(vehicleGroup.getCreateBy()); + if(null == vehicleGroup.getGroupSpecification()) { + groupDetailInfoDTO.setSpecificationJson(""); + groupDetailInfoDTO.setTags(new ArrayList<>()); + } else { + GroupSpecification groupSpecification = vehicleGroup.getGroupSpecification(); + groupDetailInfoDTO.setSpecificationJson(groupSpecification.getSpecificationJson()); + groupDetailInfoDTO.setTags(Arrays.asList(groupSpecification.getTags().split(";"))); + } + Optional groupConfigurationOptional = groupConfigurationRepository.findByGroupId(id); + if(groupConfigurationOptional.isPresent()) { + UUID dccId = groupConfigurationOptional.get().getDccId(); + Optional dataCollectionConfigOptional = dataCollectionConfigRepository.findById(dccId); + if(dataCollectionConfigOptional.isPresent()) { + groupDetailInfoDTO.setDccId(dccId); + groupDetailInfoDTO.setDccName(dataCollectionConfigOptional.get().getSubscription()); + } + } + return groupDetailInfoDTO; + } + + @Override + @Modifying + @Transactional + public void getVehicleIds(UUID id, GroupDetailInfoDTO groupDetailInfoDTO) { + Optional vehicleGroupOptional = vehicleGroupRepository.findById(id); + if(vehicleGroupOptional.isEmpty()) { + throw new MdmdsException("分组不存在", HttpStatus.CONFLICT); + } + // 根据条件获取DT所有车辆ID + Object result; + try { + result = linkDTService.getVehicleIdByCondition(groupDetailInfoDTO.getSpecificationJson()); + } catch (IOException | ExecutionException | NoSuchAlgorithmException | KeyManagementException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.CONFLICT); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ex.getMessage(), HttpStatus.CONFLICT); + } + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + JSONArray vidJSONArray = vidJSONObject.getJSONArray(RES_VEHICLE_LIST); + // 获取DT所有车辆ID,更新分组与车辆ID的关联关系 + groupVehicleRepository.deleteByGroupId(id); + List groupVehicles = new ArrayList<>(); + for(int idx = 0; idx < vidJSONArray.size(); idx++) { + GroupVehicle groupVehicle = new GroupVehicle(); + groupVehicle.setGroupId(id); + String vid = vidJSONArray.getString(idx); + groupVehicle.setVid(vid); + groupVehicles.add(groupVehicle); + } + if(!groupVehicles.isEmpty()) { + groupVehicleRepository.saveAll(groupVehicles); + } + } + + @Override + public List getAllVIDs(UUID id, GroupParamsDTO dto) { + Optional vehicleGroupOptional = vehicleGroupRepository.findById(id); + if(vehicleGroupOptional.isEmpty()) { + throw new MdmdsException(VEHICLE_GROUP_NO, HttpStatus.CONFLICT); + } + // 根据条件获取DT所有车辆ID + Object result; + try { + StringBuilder conditionSb = new StringBuilder(); + JSONObject conditionJSONObject = JSON.parseObject(dto.getSpecificationJson()); + JSONArray conditionJSONArray = conditionJSONObject.getJSONArray("and"); + for(int index = 0; index < conditionJSONArray.size(); index++){ + JSONObject itemJSONObject = conditionJSONArray.getJSONObject(index); + Set keySet = itemJSONObject.keySet(); + for(String key : keySet) { + conditionSb.append("(key").append("=").append("\"").append(key).append("\"").append(" and ") + .append(RES_VEHICLE_VALUE).append("=").append("\"").append(itemJSONObject.getString(key)).append("\")").append(" and "); + } + } + String condition = conditionSb.substring(0, conditionSb.length() - 5); + result = linkDTService.getVehicleIdByCondition(condition); + } catch (IOException | ExecutionException | NoSuchAlgorithmException | KeyManagementException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.CONFLICT); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ex.getMessage(), HttpStatus.CONFLICT); + } + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + JSONArray vidJSONArray = vidJSONObject.getJSONArray(RES_VEHICLE_LIST); + return JSON.parseArray(vidJSONArray.toJSONString(), String.class); + } + + @Override + public List getVehicleViews(UUID id, GroupParamsDTO dto) { + Optional vehicleGroupOptional = vehicleGroupRepository.findById(id); + if(vehicleGroupOptional.isEmpty()) { + throw new MdmdsException(VEHICLE_GROUP_NO, HttpStatus.CONFLICT); + } + // 并发根据车辆ID获取车辆信息 + CopyOnWriteLinkedHashMap vidInfoes; + List vidList = dto.getVidList(); + try { + vidInfoes = linkDTService.getVehicleInfoByVid(vidList); + } catch (Exception ex) { + throw new MdmdsException("DT interface concurrent call(/state-api/vehicles/{vid}/state) error: " + ex.getMessage(), HttpStatus.CONFLICT); + } + List groupVehicleResultDTOS = new ArrayList<>(); + for(Map.Entry vidInfo : vidInfoes.entrySet()) { + String vid = vidInfo.getKey(); + String info = vidInfo.getValue(); + GroupVehicleResultDTO groupVehicleResultDTO = new GroupVehicleResultDTO(); + groupVehicleResultDTO.setVid(vid); + if (!info.isEmpty()) { + JSONObject vehicleJSONObject = JSON.parseObject(info); + JSONObject infoNewJSONObject = assembleInfoJSONObject(vehicleJSONObject.keySet(), vehicleJSONObject); + groupVehicleResultDTO.setInfos(infoNewJSONObject.toJSONString()); + groupVehicleResultDTOS.add(groupVehicleResultDTO); + } else { + JSONObject infoNewJSONObject = new JSONObject(); + groupVehicleResultDTO.setInfos(infoNewJSONObject.toJSONString()); + groupVehicleResultDTOS.add(groupVehicleResultDTO); + } + } + return groupVehicleResultDTOS; + } + + private JSONObject assembleInfoJSONObject(Set keyList, JSONObject vehicleJSONObject) { + JSONObject infoNewJSONObject = new JSONObject(); + for (String key : keyList) { + if (key.contains("/")) { + continue; + } + JSONObject valueJSONObject = vehicleJSONObject.getJSONObject(key); + if (valueJSONObject.containsKey(RES_VEHICLE_VALUE)) { + infoNewJSONObject.put(key, valueJSONObject.getString(RES_VEHICLE_VALUE)); + } + } + return infoNewJSONObject; + } + + @Override + public Page pageableVehicleInfo(Pageable pageable, UUID groupId) { + return groupVehicleRepository.findAllVehiclePageable(pageable, groupId); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/LinkDTServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/LinkDTServiceImpl.java new file mode 100644 index 0000000..5c1ad01 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/LinkDTServiceImpl.java @@ -0,0 +1,293 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.DTConfiguration; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.utils.MyHttpClient; +import com.volkswagen.mdmds.utils.TokenUtil; +import org.modelmapper.internal.util.CopyOnWriteLinkedHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; + +/** + * @author Shuo Ding + * @since 2023/3/20 + */ +@Service +public class LinkDTServiceImpl implements LinkDTService { + + protected Logger log = LoggerFactory.getLogger(LinkDTServiceImpl.class); + + private final DTConfiguration dtConf; + private final ExecutorService httpFixedExecutors; + + private static final String MODULE_CONSTRUCTION_STATE = "/state-api/vehicles"; + /** 获取车辆属性字段名称 */ + private static final String GET_VEHICLE_FIELDS = MODULE_CONSTRUCTION_STATE + "/state/keys"; + /** 根据车辆字段获取字段数据 */ + private static final String GET_VEHICLE_FIELD_VALUE = MODULE_CONSTRUCTION_STATE + "/state/values"; + /** 根据车辆字段条件查询车辆VID */ + private static final String GET_VEHICLE_VID = MODULE_CONSTRUCTION_STATE + "/state/list"; + /** 获取车辆信息 */ + private static final String GET_VEHICLE_INFO = MODULE_CONSTRUCTION_STATE + "/{vid}/state"; + + private static final String REPLACE_VID = "{vid}"; + private static final String AUTHORIZATION = "Authorization"; + private static final String BEARER = "Bearer "; + private static final String HTTPS = "https"; + private static final String URI = "{uri}"; + private static final String DT_ERROR_URI = "DT interface call(" + URI + ") error: "; + + + public LinkDTServiceImpl(DTConfiguration dtConf, @Qualifier(value = "httpFixedExecutors") ExecutorService httpFixedExecutors) { + this.dtConf = dtConf; + this.httpFixedExecutors = httpFixedExecutors; + } + + private String getToken() { + if(TokenUtil.containToken(CommonField.DT_TOKEN)) { + return TokenUtil.getValue(CommonField.DT_TOKEN); + } + HttpClient httpClient = HttpClient.newBuilder() + .executor(httpFixedExecutors) + .connectTimeout(Duration.ofMillis(5000)) + .build(); + Map params = new HashMap<>(); + params.put("scope", dtConf.getScope()); + params.put("grant_type", dtConf.getGrantType()); + params.put("client_id", dtConf.getClientId()); + params.put("client_secret", dtConf.getClientSecret()); + + UriComponents uriBuilder = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getOauthUrl()) + .build(); + + HttpRequest httpRequest = HttpRequest.newBuilder(uriBuilder.toUri()) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&")))) + .timeout(Duration.ofMillis(5000)) + .build(); + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if(response.statusCode() == HttpStatus.OK.value()) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + TokenUtil.setValue(CommonField.DT_TOKEN, resultJSONObject.getString("access_token")); + return resultJSONObject.getString("access_token"); + } + log.info("认证DT获取token:statusCode={}", response.statusCode()); + } catch (IOException e) { + log.error(e.getMessage()); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + log.error(ex.getMessage()); + } + throw new MdmdsException("DT Token null", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Override + public Object getVehicleInfo(List vehicleIds) throws NoSuchAlgorithmException, KeyManagementException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + CopyOnWriteArrayList res = new CopyOnWriteArrayList<>(); + List requests = vehicleIds.stream().map(vid -> { + String path = GET_VEHICLE_INFO.replace(REPLACE_VID, vid); + UriComponents uriBuilder = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(path) + .build(); + return HttpRequest.newBuilder(uriBuilder.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(5000)); + }).map(HttpRequest.Builder::build).toList(); + + List>> futures = requests.stream() + .map(x -> httpClient.sendAsync(x, HttpResponse.BodyHandlers.ofString())) + .toList(); + + futures.stream().forEach(x -> x.whenComplete((stringHttpResponse, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + res.add(stringHttpResponse.body()); + } + })); + CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join(); + return res; + } + + @Override + public CopyOnWriteLinkedHashMap getVehicleInfoByVid(List vehicleIds) throws NoSuchAlgorithmException, KeyManagementException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + + CopyOnWriteLinkedHashMap res = new CopyOnWriteLinkedHashMap<>(); + List requests = vehicleIds.stream().map(vid -> { + String path = GET_VEHICLE_INFO.replace(REPLACE_VID, vid); + UriComponents uriBuilder = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(path) + .build(); + return HttpRequest.newBuilder(uriBuilder.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(5000)); + }).map(HttpRequest.Builder::build).toList(); + // 批量封装异步请求 + List>> futures = requests.stream() + .map(request -> httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())) + .toList(); + // 批量执行异步请求 + futures.stream().forEach(responseCompletableFuture -> responseCompletableFuture.whenComplete((stringHttpResponse, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + HttpRequest request = stringHttpResponse.request(); + String uri = request.uri().toString(); + if(uri.contains("vehicleId=")) { + String vid = uri.substring(uri.indexOf("vehicleId=") + 10); + res.put(vid, stringHttpResponse.body()); + } + } + })); + CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join(); + return res; + } + + @Override + public Object getVehicleInfo(String vid) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + String path = GET_VEHICLE_INFO.replace(REPLACE_VID, vid); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(path) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(5000)); + + HttpRequest httpRequest = requestBuilder.build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + log.info("uri:{}, result:{}", httpRequest.uri(), response); + return response.body(); + } else if(response.statusCode() == 204) { + // DT接口返回204代表查询不到车辆信息 + return "{}"; + } else { + log.error("uri:{}, statusCode:{}", httpRequest.uri(), response.statusCode()); + return response.body(); + } + } + + @Override + public Object getVehicleIdByCondition(String condition) throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(GET_VEHICLE_VID) + .queryParam("query", condition) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(5000)); + HttpRequest httpRequest = requestBuilder.build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + return response.body(); + } else if(response.statusCode() == 204) { + return "{\"vehicleList\":[]}"; + } else { + log.error("uri:{}, statusCode:{}, result={}", httpRequest.uri(), response.statusCode(), response); + throw new MdmdsException(DT_ERROR_URI.replace(URI, GET_VEHICLE_VID) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } + + @Override + public Object getAllAttributes() throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(GET_VEHICLE_FIELDS) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(30000)); + HttpRequest httpRequest = requestBuilder.build(); + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + Object resultObject = response.body(); + JSONObject resultJSONObject = JSON.parseObject(resultObject.toString()); + if(resultJSONObject.containsKey("keyList")) { + return resultJSONObject.getJSONArray("keyList"); + } else { + log.error("uri:{}, result:{}", httpRequest.uri(), response); + throw new MdmdsException(DT_ERROR_URI.replace(URI, GET_VEHICLE_FIELDS) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } else { + log.error("uri: {}, statusCode: {}, result: {}", httpRequest.uri(), response.statusCode(), response); + throw new MdmdsException(DT_ERROR_URI.replace(URI, GET_VEHICLE_FIELDS) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } + + @Override + public Object getAllEnumForAttribute(MultiValueMap params) throws IOException, InterruptedException, NoSuchAlgorithmException, KeyManagementException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(dtConf.getUrl()).path(GET_VEHICLE_FIELD_VALUE) + .queryParams(params) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(10000)); + HttpRequest httpRequest = requestBuilder.build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + if(resultJSONObject.containsKey("valueList")) { + return resultJSONObject.getJSONArray("valueList"); + } else { + log.error("uri: {}, result: {}", httpRequest.uri(), response); + throw new MdmdsException(DT_ERROR_URI.replace(URI, GET_VEHICLE_FIELD_VALUE) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } else { + log.error("uri: {}, statusCode: {}, result: {}", httpRequest.uri(), response.statusCode(), response); + throw new MdmdsException(DT_ERROR_URI.replace(URI, GET_VEHICLE_FIELD_VALUE) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/LinkHWServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/LinkHWServiceImpl.java new file mode 100644 index 0000000..ddd7f34 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/LinkHWServiceImpl.java @@ -0,0 +1,219 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.HWConfiguration; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.param.PolicyParam; +import com.volkswagen.mdmds.model.param.PolicyReqParam; +import com.volkswagen.mdmds.service.LinkHWService; +import com.volkswagen.mdmds.utils.TokenUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +@Service +public class LinkHWServiceImpl implements LinkHWService { + + protected Logger log = LoggerFactory.getLogger(LinkHWServiceImpl.class); + + private final HWConfiguration hwConf; + private final ExecutorService httpFixedExecutors; + + private static final String MODULE_CONFIG_EVENT_LIST = "/rest/ads/api/ddi-aqua/external/v1/event/list"; + private static final String MODULE_CONFIG_POLICY = "/rest/ads/api/ddi-aqua/external/v1/event/policy"; + private static final String MODULE_DATA_PULL = "/rest/ads/api/ddi-aqua/external/v1/event/data-pull"; + + private static AtomicInteger counter = new AtomicInteger(0); + + + private static final String URI = "{uri}"; + private static final String HW_ERROR_URI = "HuaWei interface call(" + URI + ") error: "; + private static final String RES_SUCCESS = "Success"; + + public LinkHWServiceImpl(HWConfiguration hwConf, @Qualifier(value = "httpFixedExecutors") ExecutorService httpFixedExecutors) { + this.hwConf = hwConf; + this.httpFixedExecutors = httpFixedExecutors; + } + + private static final String RES_ERROR_MESSAGE = "errorMessage"; + + private String getToken() { + if(TokenUtil.containToken(CommonField.HW_TOKEN)) { + return TokenUtil.getValue(CommonField.HW_TOKEN); + } + HttpClient httpClient = this.getHttpClient(); + + JSONObject bodyParam = new JSONObject(); + bodyParam.put("clientId", hwConf.getClientId()); + bodyParam.put("clientSecret", hwConf.getClientSecret()); + bodyParam.put("grantType", hwConf.getGrantType()); + bodyParam.put("scopes", hwConf.getScopes().split(",")); + + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("https").host(hwConf.getOauthUrl()) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header("Content-Type", "application/json") + .header("User-Agent", "PostmanRuntime/7.32.3") + .POST(HttpRequest.BodyPublishers.ofString(bodyParam.toJSONString())) + .timeout(Duration.ofMillis(5000)); + HttpRequest httpRequest = requestBuilder.build(); + + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + TokenUtil.setValue(CommonField.HW_TOKEN, resultJSONObject.getString("accessToken")); + return resultJSONObject.getString("accessToken"); + } else { + log.error("uri:{}, statusCode:{}", hwConf.getOauthUrl(), response.statusCode()); + throw new MdmdsException(HW_ERROR_URI.replace(URI, hwConf.getOauthUrl()) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } catch (IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + public JSONArray getEventListByAdsVersion(String adsVersion) { + JSONObject bodyParam = new JSONObject(); + bodyParam.put("adsVersion", adsVersion); + HttpClient httpClient = this.getHttpClient(); + HttpRequest httpRequest = this.getHttpRequest(this.getUriComponents(MODULE_CONFIG_EVENT_LIST), bodyParam); + + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + if(resultJSONObject.containsKey(RES_ERROR_MESSAGE) && resultJSONObject.get(RES_ERROR_MESSAGE).equals(RES_SUCCESS)) { + JSONObject dataJSONObject = resultJSONObject.getJSONObject("data"); + return dataJSONObject.getJSONArray("events"); + } else if(!resultJSONObject.get(RES_ERROR_MESSAGE).equals(RES_SUCCESS)) { + throw new MdmdsException(resultJSONObject.getString(RES_ERROR_MESSAGE), HttpStatus.ACCEPTED); + } else { + log.error("uri={}, result={}", MODULE_CONFIG_EVENT_LIST, response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_EVENT_LIST) + response, HttpStatus.ACCEPTED); + } + } else { + log.error("uri: {}, statusCode: {}, result: {}", MODULE_CONFIG_EVENT_LIST, response.statusCode(), response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_EVENT_LIST) + response, HttpStatus.valueOf(response.statusCode())); + } + } catch (IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + public JSONObject getPolicyByAdsVersionAndEvent(PolicyParam param) { + HttpClient httpClient = this.getHttpClient(); + JSONObject bodyParam = new JSONObject(); + bodyParam.put("adsVersion", param.getAdsVersion()); + bodyParam.put("events", param.getEvents()); + HttpRequest httpRequest = this.getHttpRequest(this.getUriComponents(MODULE_CONFIG_POLICY), bodyParam); + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + if(resultJSONObject.containsKey(RES_ERROR_MESSAGE) && resultJSONObject.get(RES_ERROR_MESSAGE).equals(RES_SUCCESS)) { + return resultJSONObject.getJSONObject("data"); + } else { + log.error("uri={}, result={}", MODULE_CONFIG_POLICY, response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_POLICY) + response.body(), HttpStatus.NOT_FOUND); + } + } else { + log.error("uri:{}, statusCode:{}, result:{}", MODULE_CONFIG_POLICY, response.statusCode(), response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_POLICY) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } catch (IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + @Override + public JSONObject getPolicyByOnDemandPull(PolicyReqParam param) { + HttpClient httpClient = this.getHttpClient(); + JSONObject bodyParam = new JSONObject(); + bodyParam.put("adsVersion", param.getAdsVersion()); + bodyParam.put("eventIds", param.getEvents().stream() + .map(Integer::parseInt) + .toArray(Integer[]::new)); + bodyParam.put("taskid", counter.incrementAndGet()); + long startTime = param.getStartTime(); + long endTime = param.getEndTime(); + if (startTime > endTime || endTime-startTime > 2*60*60*1000) { + throw new MdmdsException("the time interval cannot exceed 2 hours", HttpStatus.BAD_REQUEST); + } + + bodyParam.put("startTime", startTime); + bodyParam.put("endTime", endTime); + + HttpRequest httpRequest = this.getHttpRequest(this.getUriComponents(MODULE_DATA_PULL), bodyParam); + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + if(resultJSONObject.containsKey(RES_ERROR_MESSAGE) && resultJSONObject.get(RES_ERROR_MESSAGE).equals(RES_SUCCESS)) { + return resultJSONObject.getJSONObject("data"); + } else { + log.error("uri={}, result={}", MODULE_CONFIG_POLICY, response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_POLICY) + response.body(), HttpStatus.NOT_FOUND); + } + } else { + log.error("uri:{}, statusCode:{}, result:{}", MODULE_CONFIG_POLICY, response.statusCode(), response); + throw new MdmdsException(HW_ERROR_URI.replace(URI, MODULE_CONFIG_POLICY) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + } catch (IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + private HttpClient getHttpClient() { + return HttpClient.newBuilder() + .executor(httpFixedExecutors) + .connectTimeout(Duration.ofMillis(5000)) + .build(); + } + + private UriComponents getUriComponents(String path) { + return UriComponentsBuilder.newInstance() + .scheme("https").host(hwConf.getUrl()).path(path) + .build(); + } + + private HttpRequest getHttpRequest(UriComponents uriComponents, JSONObject bodyParam) { + return HttpRequest.newBuilder(uriComponents.toUri()) + .header("Content-Type", "application/json") + .header("User-Agent", "PostmanRuntime/7.32.3") + .header("Authorization", this.getToken()) + .POST(HttpRequest.BodyPublishers.ofString(bodyParam.toJSONString())) + .timeout(Duration.ofMillis(5000)) + .build(); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/LinkMSServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/LinkMSServiceImpl.java new file mode 100644 index 0000000..b46e065 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/LinkMSServiceImpl.java @@ -0,0 +1,160 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.volkswagen.mdmds.config.MSConfiguration; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.dto.MappingAllFieldDTO; +import com.volkswagen.mdmds.service.LinkMSService; +import com.volkswagen.mdmds.utils.MyHttpClient; +import com.volkswagen.mdmds.utils.TokenUtil; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; + +/** + * LinkMappingServiceImpl + * + * @author Chen Li + * @since 4/11/2025 + */ +@Service +@RequiredArgsConstructor +public class LinkMSServiceImpl implements LinkMSService { + + protected Logger log = LoggerFactory.getLogger(LinkMSServiceImpl.class); + + private static final String AUTHORIZATION = "Authorization"; + private static final String BEARER = "Bearer "; + private static final String HTTPS = "https"; + private static final String URI = "{uri}"; + private static final String MS_ERROR_URI = "MS interface call(" + URI + ") error: "; + + private static final String ALL_MAPPINGS_URL = "/api/version"; + private static final String ADS_VERSION_MAPPINGS_URL = "/api/version/mdc/%s"; + + private final ExecutorService httpFixedExecutors; + private final MSConfiguration msConfiguration; + + private String getToken() { + if(TokenUtil.containToken(CommonField.MS_TOKEN)) { + return TokenUtil.getValue(CommonField.MS_TOKEN); + } + HttpClient httpClient = HttpClient.newBuilder() + .executor(httpFixedExecutors) + .connectTimeout(Duration.ofMillis(5000)) + .build(); + Map params = new HashMap<>(); + params.put("scope", msConfiguration.getScope()); + params.put("grant_type", msConfiguration.getGrantType()); + params.put("client_id", msConfiguration.getClientId()); + params.put("client_secret", msConfiguration.getClientSecret()); + + UriComponents uriBuilder = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(msConfiguration.getOauthUrl()) + .build(); + + HttpRequest httpRequest = HttpRequest.newBuilder(uriBuilder.toUri()) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&")))) + .timeout(Duration.ofMillis(5000)) + .build(); + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if(response.statusCode() == HttpStatus.OK.value()) { + JSONObject resultJSONObject = JSON.parseObject(response.body()); + TokenUtil.setValue(CommonField.DT_TOKEN, resultJSONObject.getString("access_token")); + return resultJSONObject.getString("access_token"); + } + log.info("认证DT获取token:statusCode={}", response.statusCode()); + } catch (IOException e) { + log.error(e.getMessage()); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + log.error(ex.getMessage()); + } + throw new MdmdsException("DT Token null", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Override + public MappingAllFieldDTO getAllMappings() throws Exception { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(msConfiguration.getUrl()).path(ALL_MAPPINGS_URL) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(30000)); + HttpRequest httpRequest = requestBuilder.build(); + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + MappingAllFieldDTO mappingAllFieldDTO = null; + if (response.statusCode() == 200) { + String resultObject = response.body(); + try { + mappingAllFieldDTO = JSON.parseObject(resultObject, MappingAllFieldDTO.class); + } catch (Exception e) { + log.error("uri:{}, result:{}", httpRequest.uri(), response); + throw new MdmdsException(MS_ERROR_URI.replace(URI, ALL_MAPPINGS_URL) + response.body(), HttpStatus.valueOf(response.statusCode())); + + } + } else { + throw new MdmdsException(MS_ERROR_URI.replace(URI, ALL_MAPPINGS_URL) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + return mappingAllFieldDTO; + } + + @Override + public List getADSVersion(String mdcVersion) throws Exception { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + String path = String.format(ADS_VERSION_MAPPINGS_URL, mdcVersion); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(msConfiguration.getUrl()).path(path) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header(AUTHORIZATION, BEARER + this.getToken()) + .timeout(Duration.ofMillis(30000)); + HttpRequest httpRequest = requestBuilder.build(); + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + String resultObject = response.body(); + JSONObject resultJSONObject = JSON.parseObject(resultObject); + try { + if(JSONPath.contains(resultObject, "$.data.ADSversion[0]")) { + String eval = (String) JSONPath.eval(resultObject, "$.data.ADSversion[0]"); + return List.of(eval); + } + } catch (Exception e) { + log.error("uri:{}, result:{}", httpRequest.uri(), response); + throw new MdmdsException(MS_ERROR_URI.replace(URI, path) + response.body(), HttpStatus.valueOf(response.statusCode())); + + } + } else { + throw new MdmdsException(MS_ERROR_URI.replace(URI, path) + response.body(), HttpStatus.valueOf(response.statusCode())); + } + return List.of(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/LinkVWACServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/LinkVWACServiceImpl.java new file mode 100644 index 0000000..7c824e3 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/LinkVWACServiceImpl.java @@ -0,0 +1,154 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.VWACConfiguration; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.service.LinkVWACService; +import com.volkswagen.mdmds.utils.MyHttpClient; +import com.volkswagen.mdmds.utils.TokenUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; + +@Service +public class LinkVWACServiceImpl implements LinkVWACService { + + protected Logger log = LoggerFactory.getLogger(LinkVWACServiceImpl.class); + + private final VWACConfiguration vwacConfiguration; + private final ExecutorService httpFixedExecutors; + + private static final String MODULE_REGISTRATION = "/vehicles/api/registration"; + /** 根据VIN获取VID */ + private static final String POST_VID_BY_VIN = MODULE_REGISTRATION + "/vehicle/vehicleUuid"; + /** 根据VID获取VIN */ + private static final String GET_VIN_BY_VID = MODULE_REGISTRATION + "/vehicle/{vid}/uuid"; + + public LinkVWACServiceImpl(VWACConfiguration vwacConfiguration, ExecutorService httpFixedExecutors) { + this.vwacConfiguration = vwacConfiguration; + this.httpFixedExecutors = httpFixedExecutors; + } + + private static final String HTTPS = "https"; + private String getToken() { + if (TokenUtil.containToken(CommonField.VWAC_TOKEN)) { + return TokenUtil.getValue(CommonField.VWAC_TOKEN); + } + HttpClient httpClient = HttpClient.newBuilder() + .executor(httpFixedExecutors) + .connectTimeout(Duration.ofMillis(5000)) + .build(); + Map params = new HashMap<>(); + params.put("client_id", vwacConfiguration.getClientId()); + params.put("client_secret", vwacConfiguration.getClientSecret()); + params.put("scope", vwacConfiguration.getScope()); + params.put("grant_type", vwacConfiguration.getGrantType()); + + UriComponents uriBuilder = UriComponentsBuilder.newInstance() + .scheme(HTTPS) + .host(vwacConfiguration.getOauthUrl()) + .build(); + HttpRequest httpRequest = HttpRequest.newBuilder(uriBuilder.toUri()) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&")))) + .timeout(Duration.ofMillis(5000)) + .build(); + try { + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == HttpStatus.OK.value()) { + Object resultObject = response.body(); + JSONObject resultJSONObject = JSON.parseObject(resultObject.toString()); + TokenUtil.setValue(CommonField.VWAC_TOKEN, resultJSONObject.getString("access_token")); + return resultJSONObject.getString("access_token"); + } + log.info("认证DT获取token:statusCode={}", response.statusCode()); + } catch (IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + throw new MdmdsException("VW.AC Token null", HttpStatus.INTERNAL_SERVER_ERROR); + } + + @Override + public Object getVIDByVIN(String vin) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + MultiValueMap paramsUrl = new LinkedMultiValueMap<>(); + paramsUrl.add("api-version", "2020-07-01"); + JSONObject paramsBody = new JSONObject(); + paramsBody.put("VehicleUuid", vin); + paramsBody.put("ResponseType", "Full"); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS).host(vwacConfiguration.getUrl()).path(POST_VID_BY_VIN) + .queryParams(paramsUrl) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header("Authorization", "Bearer " + this.getToken()) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(paramsBody.toJSONString())) + .timeout(Duration.ofMillis(5000)); + HttpRequest httpRequest = requestBuilder.build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (HttpStatus.OK.value() == response.statusCode()) { + return response.body(); + } else { + JSONObject resultJSONObject = new JSONObject(); + resultJSONObject.put("StatusCode", response.statusCode()); + resultJSONObject.put("Message", response.body()); + return resultJSONObject.toJSONString(); + } + } + + @Override + public Object getVINByVID(String vid) throws NoSuchAlgorithmException, KeyManagementException, IOException, InterruptedException { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + httpClientBuilder.executor(httpFixedExecutors); + HttpClient httpClient = httpClientBuilder.build(); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("api-version", "2020-07-01"); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme(HTTPS) + .host(vwacConfiguration.getUrl()) + .path(GET_VIN_BY_VID.replace("{vid}", vid)) + .queryParams(params) + .build(); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header("Authorization", "Bearer " + this.getToken()) + .timeout(Duration.ofMillis(5000)); + HttpRequest httpRequest = requestBuilder.build(); + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (HttpStatus.OK.value() == response.statusCode()) { + return response.body(); + } else { + JSONObject resultJSONObject = new JSONObject(); + resultJSONObject.put("StatusCode", response.statusCode()); + resultJSONObject.put("Message", response.body()); + return resultJSONObject.toJSONString(); + } + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/PolicyServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/PolicyServiceImpl.java new file mode 100644 index 0000000..5871b3d --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/PolicyServiceImpl.java @@ -0,0 +1,351 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.DataCollectionConfig; +import com.volkswagen.mdmds.model.entity.GroupConfiguration; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.VehicleGroup; +import com.volkswagen.mdmds.model.param.*; +import com.volkswagen.mdmds.model.pojo.DccBriefPojo; +import com.volkswagen.mdmds.repos.DataCollectionConfigRepository; +import com.volkswagen.mdmds.repos.GroupConfigurationRepository; +import com.volkswagen.mdmds.repos.VehicleGroupRepository; +import com.volkswagen.mdmds.service.LinkHWService; +import com.volkswagen.mdmds.service.PolicyService; +import jakarta.annotation.Resource; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.DigestUtils; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Shuo Ding + * @since 2023/3/7 + */ +@Service +public class PolicyServiceImpl implements PolicyService { + + @Resource + private LinkHWService linkHWService; + + private final DataCollectionConfigRepository dccRepo; + private final GroupConfigurationRepository groupConfigurationRepository; + private final VehicleGroupRepository vehicleGroupRepository; + @PersistenceContext + private EntityManager entityManager; + + public PolicyServiceImpl(DataCollectionConfigRepository dccRepo, GroupConfigurationRepository groupConfigurationRepository, VehicleGroupRepository vehicleGroupRepository) { + this.dccRepo = dccRepo; + this.groupConfigurationRepository = groupConfigurationRepository; + this.vehicleGroupRepository = vehicleGroupRepository; + } + + @Override + @Transactional + @Modifying + public DataCollectionConfig upsertOneDCC(DccDTO dto) { + Gson gson = new Gson(); + + DataCollectionConfig dcc = new DataCollectionConfig(); + + //先判断是是否已经重复存在,使用mds而不是传参里面的sha,直接用JSON字符串的md5值 + String toJson = gson.toJson(dto); + String wholeMd5 = DigestUtils.md5DigestAsHex(toJson.getBytes(StandardCharsets.UTF_8)); + Optional byUniqueMd5 = dccRepo.findByUniqueMd5AndIsDeleted(wholeMd5, 0); + if (byUniqueMd5.isPresent()) { + throw new MdmdsException("这个配置项已经存在", HttpStatus.CONFLICT); + } + + //计算除了描述之外的MD5,这样可以更新描述,只能更新描述 + DccBriefPojo dccBriefPojo = new DccBriefPojo(); + BeanUtils.copyProperties(dto, dccBriefPojo); + String content = gson.toJson(dccBriefPojo); + String contentMd5 = DigestUtils.md5DigestAsHex(content.getBytes(StandardCharsets.UTF_8)); + Optional byContentMd5 = dccRepo.findByContentMd5AndIsDeleted(contentMd5, 0); + if (byContentMd5.isPresent()) { + DataCollectionConfig dataCollectionConfig = byContentMd5.get(); + dataCollectionConfig.setDescription(dto.getComments()); + dataCollectionConfig.setSubscription(dto.getSubscription()); + return dccRepo.save(dataCollectionConfig); + } + dcc.setUniqueMd5(wholeMd5); + dcc.setContentMd5(contentMd5); + String eventList = dto.getEvents().stream().map(EventDTO::getEventId).collect(Collectors.joining(";")); + dcc.setEventList(eventList); + dcc.setDccDetail(toJson); + dcc.setDescription(dto.getComments()); + dcc.setAdsVersion(dto.getAdsVersion()); + dcc.setSubscription(dto.getSubscription()); + dccRepo.save(dcc); + return dcc; + } + + @Override + public Page pageableBriefPolicy(Pageable pageable) { + return dccRepo.findAllDccPageable(pageable); + } + + @Override + public Page searchPolicyPage(PolicySearchParam param) { + Page policyBriefInfoDTOS = dccRepo.searchPageable(PageRequest.of(param.getPageNo() - 1, param.getPageSize()), param); + List content = policyBriefInfoDTOS.getContent(); + List dccIdList = content.stream().map(PolicyBriefInfoDTO::getId).toList(); + List configurationList = groupConfigurationRepository.findAllByDccIdIn(dccIdList); + Map> dccIdToGroupIdList = assembleDccToGroup(configurationList); + List groupIdList = configurationList.stream().map(GroupConfiguration::getGroupId).toList(); + List vehicleGroupList = vehicleGroupRepository.findAllByIdInAndIsDeletedAndStatus(groupIdList, 0, ItemStatus.ENABLE); + Map uuidToName = vehicleGroupList.stream().collect(Collectors.toMap(VehicleGroup::getId, VehicleGroup::getGroupName)); + + for(PolicyBriefInfoDTO item : content) { + List groupNameList = new ArrayList<>(); + UUID dccId = item.getId(); + if(dccIdToGroupIdList.containsKey(dccId)) { + for(UUID uuid : dccIdToGroupIdList.get(dccId)) { + if(uuidToName.containsKey(uuid)) { + String groupName = uuidToName.get(uuid); + groupNameList.add(groupName); + } + } + } + if(!groupNameList.isEmpty()) { + item.setGroupName(StringUtils.join(groupNameList, ",")); + } + } + + return policyBriefInfoDTOS; + } + + private Map> assembleDccToGroup(List configurationList) { + Map> dccIdToGroupIdList = new HashMap<>(); + for(GroupConfiguration groupConfiguration : configurationList) { + if(dccIdToGroupIdList.containsKey(groupConfiguration.getDccId())) { + dccIdToGroupIdList.get(groupConfiguration.getDccId()).add(groupConfiguration.getGroupId()); + } else { + List initIdList = new ArrayList<>(); + initIdList.add(groupConfiguration.getGroupId()); + dccIdToGroupIdList.put(groupConfiguration.getDccId(), initIdList); + } + } + return dccIdToGroupIdList; + } + + @Override + public PolicyBriefInfoDTO getPolicyInfo(UUID id) { + Optional dataCollectionConfigOptional = dccRepo.findById(id); + if (dataCollectionConfigOptional.isEmpty()) { + throw new MdmdsException("配置不存在", HttpStatus.CONFLICT); + } + PolicyBriefInfoDTO policyBriefInfoDTO = new PolicyBriefInfoDTO(); + BeanUtils.copyProperties(dataCollectionConfigOptional.get(), policyBriefInfoDTO); + return policyBriefInfoDTO; + } + + @Override + public List getPolicyViews(PolicyParamsDTO dto) { + List policyBriefInfoDTOS = new ArrayList<>(); + String adsVersion = dto.getAdsVersion(); + List dataCollectionConfigs = dccRepo.findAllByAdsVersionAndIsDeleted(adsVersion, 0); + for (DataCollectionConfig dataCollectionConfig : dataCollectionConfigs) { + PolicyBriefInfoDTO policyBriefInfoDTO = new PolicyBriefInfoDTO(); + BeanUtils.copyProperties(dataCollectionConfig, policyBriefInfoDTO); + policyBriefInfoDTOS.add(policyBriefInfoDTO); + } + return policyBriefInfoDTOS; + } + + @Override + public void save(PolicySaveParam param) { + PolicyBaseDTO policySaveDTO = new PolicyBaseDTO(); + BeanUtils.copyProperties(param, policySaveDTO); + + String baseToJson = new Gson().toJson(policySaveDTO); + String baseMd5 = DigestUtils.md5DigestAsHex(baseToJson.getBytes(StandardCharsets.UTF_8)); + Optional byUniqueMd5 = dccRepo.findByUniqueMd5AndIsDeleted(baseMd5, 0); + if(byUniqueMd5.isPresent()) { + DataCollectionConfig dataCollectionConfig = byUniqueMd5.get(); + dataCollectionConfig.setDescription(param.getComments()); + dataCollectionConfig.setSubscription(param.getSubscription()); + dccRepo.save(dataCollectionConfig); + } else { + DataCollectionConfig dcc = new DataCollectionConfig(); + dcc.setUniqueMd5(baseMd5); + dcc.setDescription(param.getComments()); + dcc.setSubscription(param.getSubscription()); + dcc.setAdsVersion(param.getAdsVersion()); + dcc.setEventList(param.getEvents().stream().map(PolicySaveParam.EventParam::getEventId).collect(Collectors.joining(";"))); + dcc.setDccDetail(baseToJson); + dccRepo.save(dcc); + } + } + + @Override + public void create(PolicyCreateParam param) { + String apiForm = param.getApiForm(); + if(apiForm.equals("Common")) { + List events = param.getEvents(); + if(events.isEmpty()) { + throw new MdmdsException("Event ID needs to be selected", HttpStatus.CONFLICT); + } + // 降序 + events = events.stream().sorted(Comparator.comparing(PolicyCreateParam.EventParam::getEventId)).toList(); + + String adsVersion = param.getAdsVersion(); + // 获取configuration + PolicyParam policyParam = new PolicyParam(); + policyParam.setAdsVersion(adsVersion); + policyParam.setEvents(assembleEventList(events)); + JSONObject resultJSONObject = linkHWService.getPolicyByAdsVersionAndEvent(policyParam); + String sha256 = resultJSONObject.getString("sha256"); + String configuration = resultJSONObject.getString("configuration"); + // 持久化数据 + PolicyBaseDTO policyCreateDTO = new PolicyBaseDTO(); + policyCreateDTO.setAdsVersion(adsVersion); + policyCreateDTO.setSha256(sha256); + policyCreateDTO.setConfiguration(configuration); + policyCreateDTO.setEvents(events); + String baseToJson = new Gson().toJson(policyCreateDTO); + String baseMd5 = DigestUtils.md5DigestAsHex(baseToJson.getBytes(StandardCharsets.UTF_8)); + Optional byUniqueMd5 = dccRepo.findByUniqueMd5AndIsDeleted(baseMd5, 0); + if(byUniqueMd5.isPresent()) { + DataCollectionConfig dataCollectionConfig = byUniqueMd5.get(); + String dbSubscription = dataCollectionConfig.getSubscription(); + if(!dbSubscription.equals(param.getSubscription())) { + // Configuration已经存在,Subscription不可修改 + throw new MdmdsException("Configuration already exists, Subscription is '" + dbSubscription + "'", HttpStatus.CONFLICT); + } + dataCollectionConfig.setDescription(param.getComments()); + dataCollectionConfig.setSubscription(param.getSubscription()); + dccRepo.save(dataCollectionConfig); + } else { + // Subscription唯一 + List list = dccRepo.findAllBySubscriptionAndIsDeleted(param.getSubscription(), 0); + if(list != null && !list.isEmpty()) { + throw new MdmdsException("Subscription already exists", HttpStatus.CONFLICT); + } + DataCollectionConfig dcc = new DataCollectionConfig(); + dcc.setApiForm(apiForm); + dcc.setUniqueMd5(baseMd5); + dcc.setDescription(param.getComments()); + dcc.setSubscription(param.getSubscription()); + dcc.setAdsVersion(param.getAdsVersion()); + dcc.setEventList(param.getEvents().stream().map(PolicyCreateParam.EventParam::getEventId).collect(Collectors.joining(";"))); + dcc.setDccDetail(baseToJson); + dcc.setIsDeleted(0); + dccRepo.save(dcc); + } + } else if(apiForm.equals("On-Demand Pull")) { +// if(StringUtils.isEmpty(param.getStartTime()) || StringUtils.isEmpty(param.getEndTime())) { +// throw new MdmdsException("Time needs to be selected", HttpStatus.CONFLICT); +// } + List events = param.getEvents(); + if(events.isEmpty()) { + throw new MdmdsException("Event ID needs to be selected", HttpStatus.CONFLICT); + } + // 降序 + events = events.stream().sorted(Comparator.comparing(PolicyCreateParam.EventParam::getEventId)).toList(); + + String adsVersion = param.getAdsVersion(); + List timeSlotList = param.getTimeSlot(); + // 获取configuration + PolicyReqParam policyReqParam = new PolicyReqParam(); + policyReqParam.setAdsVersion(adsVersion); + policyReqParam.setEvents(assembleEventList(events)); + policyReqParam.setStartTime(timeSlotList.get(0)); + policyReqParam.setEndTime(timeSlotList.get(1)); + JSONObject resultJSONObject = linkHWService.getPolicyByOnDemandPull(policyReqParam); + String taskid = resultJSONObject.getString("taskid"); + String sha256 = resultJSONObject.getString("sha256"); + String configuration = resultJSONObject.getString("configuration"); + // 持久化数据 + PolicyBaseDTO policyCreateDTO = new PolicyBaseDTO(); + policyCreateDTO.setAdsVersion(adsVersion); + policyCreateDTO.setSha256(sha256); + policyCreateDTO.setConfiguration(configuration); + policyCreateDTO.setEvents(events); + policyCreateDTO.setStartTime(ZonedDateTime.ofInstant(Instant.ofEpochMilli(timeSlotList.get(0)), ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + policyCreateDTO.setEndTime(ZonedDateTime.ofInstant(Instant.ofEpochMilli(timeSlotList.get(1)), ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + String baseToJson = new Gson().toJson(policyCreateDTO); + String baseMd5 = DigestUtils.md5DigestAsHex(baseToJson.getBytes(StandardCharsets.UTF_8)); + Optional byUniqueMd5 = dccRepo.findByUniqueMd5AndIsDeleted(baseMd5, 0); + if(byUniqueMd5.isPresent()) { + DataCollectionConfig dataCollectionConfig = byUniqueMd5.get(); + String dbSubscription = dataCollectionConfig.getSubscription(); + if(!dbSubscription.equals(param.getSubscription())) { + // Configuration已经存在,Subscription不可修改 + throw new MdmdsException("Configuration already exists, Subscription is '" + dbSubscription + "'", HttpStatus.CONFLICT); + } + dataCollectionConfig.setDescription(param.getComments()); + dataCollectionConfig.setSubscription(param.getSubscription()); + dccRepo.save(dataCollectionConfig); + } else { + // Subscription唯一 + List list = dccRepo.findAllBySubscriptionAndIsDeleted(param.getSubscription(), 0); + if(list != null && !list.isEmpty()) { + throw new MdmdsException("Subscription already exists", HttpStatus.CONFLICT); + } + DataCollectionConfig dcc = new DataCollectionConfig(); + dcc.setApiForm(apiForm); + dcc.setTaskId(""); +// dcc.setStartTime(policyReqParam.getStartTime()); +// dcc.setEndTime(policyReqParam.getEndTime()); +// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); +// dcc.setStartTime(sdf.parse(timeSlotList.get(0))); +// dcc.setEndTime(sdf.parse(timeSlotList.get(1))); + dcc.setUniqueMd5(baseMd5); + dcc.setDescription(param.getComments()); + dcc.setSubscription(param.getSubscription()); + dcc.setAdsVersion(param.getAdsVersion()); + dcc.setEventList(param.getEvents().stream().map(PolicyCreateParam.EventParam::getEventId).collect(Collectors.joining(";"))); + dcc.setDccDetail(baseToJson); + dcc.setIsDeleted(0); + dccRepo.save(dcc); + } + } else { + throw new MdmdsException("Event ID needs to be selected", HttpStatus.NOT_FOUND); + } + } + + @Override + public void deleteConfigurationByIds(List idList) { + List toGroupList = groupConfigurationRepository.findAllByDccIdIn(idList); + if(toGroupList != null && !toGroupList.isEmpty()) { + List groupUUIDList = toGroupList.stream().map(GroupConfiguration::getGroupId).toList(); + List vehicleGroupList = vehicleGroupRepository.findAllByIdInAndIsDeleted(groupUUIDList, 0); + if(null != vehicleGroupList && !vehicleGroupList.isEmpty()) { + // Configuration和vehicleGroup关联 + List vehicleGroupNameList = vehicleGroupList.stream().map(VehicleGroup::getGroupName).toList(); + throw new MdmdsException("Configuration Associated Vehicles:[" + String.join("|", vehicleGroupNameList) + "]", HttpStatus.CONFLICT); + } + } + List list = dccRepo.findAllById(idList); + list.stream().forEach(configuration -> configuration.setIsDeleted(1)); + dccRepo.saveAll(list); + } + + private List assembleEventList(List events) { + List eventList = new ArrayList<>(); + for(PolicyCreateParam.EventParam event : events) { + eventList.add(event.getEventId()); + } + return eventList; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/TicketServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/TicketServiceImpl.java new file mode 100644 index 0000000..b0c56de --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/TicketServiceImpl.java @@ -0,0 +1,343 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.*; +import com.volkswagen.mdmds.model.param.TicketParam; +import com.volkswagen.mdmds.model.param.TicketUpdateParam; +import com.volkswagen.mdmds.model.pojo.TicketVehicleInfoPojo; +import com.volkswagen.mdmds.model.vo.TicketVo; +import com.volkswagen.mdmds.repos.TicketRepository; +import com.volkswagen.mdmds.repos.TicketVehicleRepository; +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.service.LinkVWACService; +import com.volkswagen.mdmds.service.TicketService; +import com.volkswagen.mdmds.service.VehicleService; +import com.volkswagen.mdmds.utils.AntStrUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.modelmapper.internal.util.CopyOnWriteLinkedHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.http.HttpStatus; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +@Service +public class TicketServiceImpl implements TicketService { + + protected Logger log = LoggerFactory.getLogger(TicketServiceImpl.class); + + private static final String TICKET_NOT_EXIST = "The ticket does not exist"; + private static final String TICKET_HOLD = "The ticket is locked"; + + @Resource + private LinkDTService linkDTService; + + @Resource + private LinkVWACService linkVWACService; + + @Resource + private VehicleService vehicleService; + + + private final TicketRepository ticketRepository; + private final TicketVehicleRepository ticketVehicleRepository; + + public TicketServiceImpl(TicketRepository ticketRepository, TicketVehicleRepository ticketVehicleRepository) { + this.ticketRepository = ticketRepository; + this.ticketVehicleRepository = ticketVehicleRepository; + } + + @Override + public Ticket createTicket(TicketBriefInfoDTO dto) { + List list = ticketRepository.findAllByTicketNameEqualsAndIsDeleted(dto.getTicketName(), 0); + if(!list.isEmpty()) { + throw new MdmdsException("Ticket name already exists", HttpStatus.CONFLICT); + } + Ticket ticket = new Ticket(); + BeanUtils.copyProperties(dto, ticket); + ticket.setIsDeleted(0); + ticket.setTotal(0); + ticketRepository.save(ticket); + return ticket; + } + + @Override + @Modifying + @Transactional + public Ticket addVinToTicket(UUID id, String vin) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + // VW.AC根据vin获取vid + String vid = null; + try { + Object result = linkVWACService.getVIDByVIN(vin); + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + vid = vidJSONObject.getString("VehicleId"); + } catch (NoSuchAlgorithmException | KeyManagementException | IOException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + if (null == vid) { + throw new MdmdsException("VW.AC can not find vid", HttpStatus.NOT_FOUND); + } + // 保存工单关联的车辆 + Ticket ticket = ticketOptional.get(); + TicketVehicle ticketVehicle = new TicketVehicle(); + ticketVehicle.setTicketId(id); + ticketVehicle.setVin(vin); + ticketVehicle.setVid(vid); + ticketVehicleRepository.save(ticketVehicle); + return ticket; + } + + @Override + public Page pageableBriefTicket(Pageable pageable) { + Page allDccPageable = ticketRepository.findAllTicketPageable(pageable); + for (TicketBriefInfoDTO entity : allDccPageable.getContent()) { + this.assembleStatusDes(entity); + } + return allDccPageable; + } + @Override + public Page pageableTicket(int pageNo, int pageSize, TicketParam param) { + Pageable pageable = PageRequest.of(pageNo - 1, pageSize); + if (param.getStatus().equals(ItemStatus.ALL)) { + param.setStatus(null); + } +// if ((!param.getTotalMin().isEmpty() && !StringUtils.isNumeric(param.getTotalMin())) || +// (!param.getTotalMax().isEmpty() && !StringUtils.isNumeric(param.getTotalMax()))) { +// throw new MdmdsException("Unreasonable transmission of parameters", HttpStatus.UNPROCESSABLE_ENTITY); +// } + if(!param.getVin().isEmpty() && !AntStrUtil.isVIN(param.getVin())) { + throw new MdmdsException(CommonField.VIN_ERROR, HttpStatus.NOT_FOUND); + } + Page ticketVoPage = ticketRepository.findAllTicketPageable(pageable, param); + for (TicketVo entity : ticketVoPage.getContent()) { + this.assembleStatusDes(entity); + } + return ticketVoPage; + } + private void assembleStatusDes(TicketVo entity) { + if (entity.getStatus().equals(ItemStatus.NONE)) { + entity.setStatusDes("Ticket has no associated vehicles"); + } else if (entity.getStatus().equals(ItemStatus.RUN)) { + entity.setStatusDes("Ticket is associating vehicles"); + } else if (entity.getStatus().equals(ItemStatus.HOLD)) { + entity.setStatusDes("Ticket related vehicles to be reviewed"); + } else if (entity.getStatus().equals(ItemStatus.DONE)) { + entity.setStatusDes("Ticket Associated Vehicle Approval Passed"); + } + } + private void assembleStatusDes(TicketBriefInfoDTO entity) { + if (entity.getStatus().equals(ItemStatus.NONE)) { + entity.setStatusDes("Ticket has no associated vehicles"); + } else if (entity.getStatus().equals(ItemStatus.RUN)) { + entity.setStatusDes("Ticket is associating vehicles"); + } else if (entity.getStatus().equals(ItemStatus.HOLD)) { + entity.setStatusDes("Ticket related vehicles to be reviewed"); + } else if (entity.getStatus().equals(ItemStatus.DONE)) { + entity.setStatusDes("Ticket Associated Vehicle Approval Passed"); + } + } + + @Override + public Ticket updateTicketDescription(UUID id, TicketUpdateParam dto) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + ticketOptional.get().setTicketDetail(dto.getTicketDetail()); + ticketRepository.save(ticketOptional.get()); + return ticketOptional.get(); + } + + @Override + public Ticket changeTicketStatus(UUID id, TicketBriefInfoDTO dto) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + Ticket ticket = ticketOptional.get(); + if (!ticket.getStatus().equals(ItemStatus.HOLD)) { + throw new MdmdsException(TICKET_HOLD, HttpStatus.CONFLICT); + } + ticket.setStatus(ItemStatus.DONE); + ticketRepository.save(ticket); + return ticketOptional.get(); + } + + @Override + public Ticket deleteTicketById(UUID id) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + + Ticket ticket = ticketOptional.get(); + ticket.setIsDeleted(1); + ticketRepository.save(ticket); + return ticketOptional.get(); + } + + @Override + public void deleteTicketByIds(List idList) { + List ticketList = ticketRepository.findByIdIn(idList); + ticketList.stream().forEach(ticket -> ticket.setIsDeleted(1)); + ticketRepository.saveAll(ticketList); + } + + @Override + public TicketDetailDTO getTicketDetail(UUID id) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + TicketDetailDTO ticketDetailDTO = new TicketDetailDTO(); + Ticket ticket = ticketOptional.get(); + BeanUtils.copyProperties(ticket, ticketDetailDTO); + ticketDetailDTO.setCreateBy(ticket.getCreateBy()); + ticketDetailDTO.setLastModifiedBy(ticket.getLastModifiedBy()); + return ticketDetailDTO; + } + + @Override + @Modifying + @Transactional + public void batchVehicleInsertToTicket(String ticketName, List vehicleInfoDTOList) { + Ticket ticket = new Ticket(); + ticket.setTicketName(ticketName); + ticket.setStatus(ItemStatus.HOLD); + ticketRepository.save(ticket); + List ticketVehicleList = new ArrayList<>(); + for (VehicleInfoDTO vehicleInfoDTO : vehicleInfoDTOList) { + TicketVehicle ticketVehicle = new TicketVehicle(); + ticketVehicle.setTicketId(ticket.getId()); + ticketVehicle.setVid(vehicleInfoDTO.getVid()); + ticketVehicleList.add(ticketVehicle); + } + ticketVehicleRepository.saveAll(ticketVehicleList); + } + + @Override + public List getVehicleViews(UUID id, TicketParamsDTO dto) { + Optional ticketOptional = ticketRepository.findById(id); + if (ticketOptional.isEmpty()) { + throw new MdmdsException(TICKET_NOT_EXIST, HttpStatus.CONFLICT); + } + // 并发根据车辆ID获取车辆信息 + CopyOnWriteLinkedHashMap vidInfoes; + List vidList = dto.getVidList(); + try { + vidInfoes = linkDTService.getVehicleInfoByVid(vidList); + } catch (Exception ex) { + log.error("从DT接口获取所有车辆信息(/ConstructionState/get): {}", ex.getMessage()); + throw new MdmdsException("Digital Twin接口调用错误", HttpStatus.CONFLICT); + } + List ticketVehicleResultDTOS = new ArrayList<>(); + for (Map.Entry vidInfo : vidInfoes.entrySet()) { + ticketVehicleResultDTOS.add(assembleTicketVehicle(vidInfo)); + } + return ticketVehicleResultDTOS; + } + + private TicketVehicleResultDTO assembleTicketVehicle(Map.Entry vidInfo) { + String vid = vidInfo.getKey(); + String info = vidInfo.getValue(); + TicketVehicleResultDTO ticketVehicleResultDTO = new TicketVehicleResultDTO(); + ticketVehicleResultDTO.setVid(vid); + if (!info.isEmpty()) { + JSONObject vehicleJSONObject = JSON.parseObject(info); + JSONObject infoNewJSONObject = new JSONObject(); + Set keyList = vehicleJSONObject.keySet(); + for (String key : keyList) { + if (key.contains("/")) { + continue; + } + JSONObject valueJSONObject = vehicleJSONObject.getJSONObject(key); + if (valueJSONObject.containsKey("value")) { + infoNewJSONObject.put(key, valueJSONObject.getString("value")); + } + } + ticketVehicleResultDTO.setInfos(infoNewJSONObject.toJSONString()); + } else { + JSONObject infoNewJSONObject = new JSONObject(); + ticketVehicleResultDTO.setInfos(infoNewJSONObject.toJSONString()); + } + return ticketVehicleResultDTO; + } + + @Async + @Override + @Modifying + @Transactional + public void updateGroupVinAndInfo(Ticket ticket, TicketParamsDTO dto) { + ticket.setStatus(ItemStatus.HOLD); + List vinList = dto.getVinList(); + ticket.setTotal(vinList.size()); + ticket.setVines(StringUtils.join(vinList, ",")); + ticketRepository.save(ticket); + List> vinPartitionList = Lists.partition(vinList, 10); + List targetList = new ArrayList<>(); + for (List vinItemList : vinPartitionList) { + Map succItemMap = new HashMap<>(); + List vidItemList = new ArrayList<>(); + VehicleParamsDTO vehicleParamsDTO = VehicleParamsDTO.builder().vinList(vinItemList).build(); + // 根据VIN从VW.AC获取VID,若VID获取失败记录 + List vehicleReturnDTOVidList = vehicleService.getVidList(vehicleParamsDTO); + for (VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOVidList) { + if (null != vehicleReturnDTO.getStatusCode()) { + targetList.add(vehicleReturnDTO); + } else { + String vid = vehicleReturnDTO.getVid(); + succItemMap.put(vid, vehicleReturnDTO.getVin()); + vidItemList.add(vid); + } + } + // 根据VIN从DT获取车辆信息,失败记录 + vehicleParamsDTO = VehicleParamsDTO.builder().vidList(vidItemList).build(); + List vehicleReturnDTOList = vehicleService.getVehicleInfoList(vehicleParamsDTO); + for (VehicleReturnDTO vehicleReturnDTO : vehicleReturnDTOList) { + String vid = vehicleReturnDTO.getVid(); + vehicleReturnDTO.setVin(succItemMap.get(vid)); + targetList.add(vehicleReturnDTO); + } + } + List ticketVehicles = new ArrayList<>(); + for (VehicleReturnDTO vehicleReturnDTO : targetList) { + TicketVehicle ticketVehicle = new TicketVehicle(); + ticketVehicle.setTicketId(ticket.getId()); + BeanUtils.copyProperties(vehicleReturnDTO, ticketVehicle); + ticketVehicles.add(ticketVehicle); + } + if (!ticketVehicles.isEmpty()) { + ticketVehicleRepository.saveAll(ticketVehicles); + } + } + + @Override + public Page pageableVehicleInfo(Pageable pageable, UUID ticketId) { + return ticketVehicleRepository.findAllVehiclePageable(pageable, ticketId); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/UserServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..6e0b421 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/UserServiceImpl.java @@ -0,0 +1,278 @@ +package com.volkswagen.mdmds.service.impl; + +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.model.dto.*; +import com.volkswagen.mdmds.model.entity.DicResource; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import com.volkswagen.mdmds.model.entity.RoleInfo; +import com.volkswagen.mdmds.model.entity.UserInfo; +import com.volkswagen.mdmds.model.param.RoleCreateParam; +import com.volkswagen.mdmds.model.param.UserStatusParam; +import com.volkswagen.mdmds.model.vo.ResourceVo; +import com.volkswagen.mdmds.model.vo.RoleResourceTreeVo; +import com.volkswagen.mdmds.repos.DicResourceRepository; +import com.volkswagen.mdmds.repos.RoleInfoRepository; +import com.volkswagen.mdmds.repos.UserInfoRepository; +import com.volkswagen.mdmds.service.UserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class UserServiceImpl implements UserService { + + private static final String RES_ROLE_NAME = "roleName"; + + // 用户表操作对象 + private final UserInfoRepository userInfoRepository; + private final RoleInfoRepository roleInfoRepository; + private final DicResourceRepository dicResourceRepository; + + public UserServiceImpl(UserInfoRepository userInfoRepository, RoleInfoRepository roleInfoRepository, DicResourceRepository dicResourceRepository) { + this.userInfoRepository = userInfoRepository; + this.roleInfoRepository = roleInfoRepository; + this.dicResourceRepository = dicResourceRepository; + } + + @Override + public UserInfoDTO initInfo(UserInfoDTO userInfoDTO) { + UserInfo userInfo = new UserInfo(); + String userName = userInfoDTO.getUserName(); + List roles = userInfoDTO.getRoleList(); + Optional byUserName = userInfoRepository.findByUserName(userName); + + BeanUtils.copyProperties(userInfoDTO, userInfo); + Instant nowTime = Instant.now(); + if (byUserName.isEmpty()) { + userInfo.setCreationDate(Date.from(nowTime)); + userInfo.setLastModifiedDate(Date.from(nowTime)); + userInfo.setStatus(ItemStatus.ENABLE); + } else { + userInfo.setId(byUserName.get().getId()); + userInfo.setLastModifiedDate(Date.from(nowTime)); + userInfo.setStatus(byUserName.get().getStatus()); + } + + List roleNameList = roles.stream().map(RoleInfoDTO::getRoleName).toList(); + if (roleNameList.isEmpty()) { + // 用户Token没有角色 + userInfoRepository.save(userInfo); + } else { + userInfo.setRoles(String.join(",", roleNameList)); + List> byRoleNameIn = roleInfoRepository.findByRoleNameIn(roleNameList); + if (byRoleNameIn.isEmpty()) { + // 用户Token角色在数据库未匹配 + userInfoRepository.save(userInfo); + } else { + Set roleInfoSet = new HashSet<>(); + byRoleNameIn.stream().forEach(roleInfoOptional -> roleInfoSet.add(roleInfoOptional.get())); + userInfo.setRoleInfoes(roleInfoSet); + userInfoRepository.save(userInfo); + } + } + userInfoDTO.setId(userInfo.getId()); + userInfoDTO.setRoles(userInfo.getRoles()); + userInfoDTO.setRoleList(null); + List realRoles = userInfo.getRoleInfoes().stream().map(RoleInfo::getRoleName).toList(); + userInfoDTO.setRealRoles(realRoles); + List> resources = roleInfoRepository.findResourceInRoleName(realRoles); + userInfoDTO.setResources(resources); + userInfoDTO.setStatus(userInfo.getStatus()); + return userInfoDTO; + } + + @Override + public Page pageableUserInfos(Pageable pageable) { + return userInfoRepository.findAllUserInfoPageable(pageable); + } + + @Override + public void alterUserStatus(UUID id, UserStatusParam param) { + Optional userInfoOptional = userInfoRepository.findById(id); + if(userInfoOptional.isEmpty()) { + throw new MdmdsException("User does not exist", HttpStatus.CONFLICT); + } + UserInfo userInfo = userInfoOptional.get(); + if(userInfoOptional.get().getRoles().contains(CommonField.IDP_ROLE_ADMIN)) { + throw new MdmdsException("no permission", HttpStatus.CONFLICT); + } + userInfo.setStatus(param.getStatus()); + userInfoRepository.save(userInfo); + } + + @Override + public Page pageableRoleInfos(Pageable pageable) { + Page result = roleInfoRepository.findAllRoleInfoPageable(pageable); + + Map> roleNameToResourceName = new HashMap<>(); + List roleNameList = new ArrayList<>(); + List list = result.getContent(); + for(RoleInfoDTO roleInfo : list) { + roleNameList.add(roleInfo.getRoleName()); + } + List> roleNameToResource = roleInfoRepository.findResourceInRoleName(roleNameList); + for(Map resource : roleNameToResource) { + if(roleNameToResourceName.containsKey((String) resource.get(RES_ROLE_NAME))) { + roleNameToResourceName.get((String) resource.get(RES_ROLE_NAME)).add((String) resource.get("resName")); + } else { + List initList = new ArrayList<>(); + initList.add((String) resource.get("resName")); + roleNameToResourceName.put((String) resource.get(RES_ROLE_NAME), initList); + } + } + for(RoleInfoDTO roleInfo : list) { + if(roleNameToResourceName.containsKey(roleInfo.getRoleName())) { + roleInfo.setResName(String.join(",", roleNameToResourceName.get(roleInfo.getRoleName()))); + } + } + return result; + } + + @Override + public void deleteRoleById(UUID id) { + Optional roleInfoOptional = roleInfoRepository.findById(id); + if (roleInfoOptional.isEmpty()) { + throw new MdmdsException("Role does not exist", HttpStatus.CONFLICT); + } + + if(roleInfoOptional.get().getRoleName().equals(CommonField.IDP_ROLE_ADMIN) || + roleInfoOptional.get().getRoleName().equals(CommonField.IDP_ROLE_USER)) { + throw new MdmdsException("The basic role cannot be deleted", HttpStatus.CONFLICT); + } +// roleInfoRepository.delete(roleInfoOptional.get()); + roleInfoRepository.deleteById(id); + } + + @Override + public Page pageableResourceInfos(Pageable pageable) { + return dicResourceRepository.findAllResourceInfoPageable(pageable); + } + + @Override + public List getRoleItem() { + List roleInfoDTOS = new ArrayList<>(); + List roleInfos = roleInfoRepository.findRoleItem(); + for(RoleInfo role : roleInfos) { + RoleInfoDTO roleInfoDTO = new RoleInfoDTO(); + roleInfoDTO.setId(role.getId()); + roleInfoDTO.setRoleName(role.getRoleName()); + roleInfoDTOS.add(roleInfoDTO); + } + return roleInfoDTOS; + } + + @Override + public List getResourceItem() { + List dicResourceDTOS = new ArrayList<>(); + List dicResources = dicResourceRepository.findResourceItem(); + for(DicResource resource : dicResources) { + DicResourceDTO dicResourceDTO = new DicResourceDTO(); + dicResourceDTO.setResId(resource.getId()); + dicResourceDTO.setResName(resource.getResName()); + dicResourceDTO.setResUrl(resource.getResUrl()); + dicResourceDTOS.add(dicResourceDTO); + } + return dicResourceDTOS; + } + + @Override + public List getTreeItem() { + List result = new ArrayList<>(); + List roleList = roleInfoRepository.findRoleItem(); + List resourceList = dicResourceRepository.findResourceItem(); + Map nameToItem = resourceList.stream().collect(Collectors.toMap(DicResource::getResName, Function.identity())); + for(RoleInfo roleInfo : roleList) { + RoleResourceTreeVo roleResourceTreeVo = new RoleResourceTreeVo(); + roleResourceTreeVo.setRoleId(roleInfo.getId()); + roleResourceTreeVo.setRoleName(roleInfo.getRoleName()); + Set dicResources = roleInfo.getDicResources(); + List dicResourceList = dicResources.stream().map(DicResource::getResName).toList(); + List resourceVos = new ArrayList<>(); + if(null != roleInfo.getInnerRole()) { + List roleInnerList = Arrays.asList(roleInfo.getInnerRole().split(",")); + for(String roleInner : roleInnerList) { + assembleResourceVo(roleInner, nameToItem, dicResourceList, resourceVos); + } + } + roleResourceTreeVo.setResources(resourceVos); + result.add(roleResourceTreeVo); + } + return result; + } + + private void assembleResourceVo(String roleInner, Map nameToItem, List dicResourceList, List resourceVos) { + if(CommonField.INNER_MENU.containsKey(roleInner) && nameToItem.containsKey(CommonField.INNER_MENU.get(roleInner))) { + DicResource resourceEntity = nameToItem.get(CommonField.INNER_MENU.get(roleInner)); + ResourceVo resourceVo = new ResourceVo(); + resourceVo.setResId(resourceEntity.getId()); + resourceVo.setResName(resourceEntity.getResName()); + resourceVo.setResUrl(resourceEntity.getResUrl()); + if(dicResourceList.contains(CommonField.INNER_MENU.get(roleInner))) { + resourceVo.setChecked(Boolean.TRUE); + } + resourceVos.add(resourceVo); + } + } + + @Override + public void setRoleResource(RoleResourceDetailDTO dto) { + UUID roleId = dto.getId(); + Set dicResourceDTOS = dto.getResource(); + Optional roleInfoOptional = roleInfoRepository.findById(roleId); + if (roleInfoOptional.isEmpty()) { + throw new MdmdsException("Role does not exist", HttpStatus.CONFLICT); + } + List resourceIds = dicResourceDTOS.stream().map(DicResourceDTO::getResId).toList(); + List dicResources = dicResourceRepository.findAllById(resourceIds); + if (dicResources.isEmpty()) { + throw new MdmdsException("Resource does not exist", HttpStatus.CONFLICT); + } + + List resNameList = dicResources.stream().map(DicResource::getResName).toList(); + RoleInfo roleInfo = roleInfoOptional.get(); + if(roleInfo.getRoleName().equals(CommonField.IDP_ROLE_ADMIN)) { + String innerRoles = roleInfo.getInnerRole(); + if(!innerRoles.isEmpty()) { + List innerRoleList = Arrays.asList(innerRoles.split(",")); + for(String innerRoleName : innerRoleList) { + if(resNameList.contains(CommonField.INNER_MENU.get(innerRoleName))) { + throw new MdmdsException("Basic role permissions cannot be deleted", HttpStatus.CONFLICT); + } + } + } + } + + Set dicResourceSet = new HashSet<>(dicResources); + roleInfoOptional.get().setDicResources(dicResourceSet); + roleInfoRepository.save(roleInfoOptional.get()); + } + + @Override + public List> getAllResourceView() { + return dicResourceRepository.findAllResourceViews(); + } + + @Override + public void addRole(RoleCreateParam param) { + String roleName = param.getRoleName(); + List> list = roleInfoRepository.findByRoleNameIn(Arrays.asList(roleName)); + if(!list.isEmpty()) { + throw new MdmdsException("Role name already exists", HttpStatus.CONFLICT); + } + RoleInfo roleInfo = new RoleInfo(); + roleInfo.setRoleName(roleName); + // 设置创建角色的默认权限 + roleInfo.setInnerRole(StringUtils.join(CommonField.COMMON_RESOURCE, ",")); + roleInfoRepository.save(roleInfo); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/service/impl/VehicleServiceImpl.java b/src/main/java/com/volkswagen/mdmds/service/impl/VehicleServiceImpl.java new file mode 100644 index 0000000..5b45309 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/service/impl/VehicleServiceImpl.java @@ -0,0 +1,177 @@ +package com.volkswagen.mdmds.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.model.dto.VehicleParamsDTO; +import com.volkswagen.mdmds.model.dto.VehicleReturnDTO; +import com.volkswagen.mdmds.repos.VehicleInfoRepository; +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.service.LinkVWACService; +import com.volkswagen.mdmds.service.VehicleService; +import com.volkswagen.mdmds.utils.AntThreadPoolUtil; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.ObjectUtils; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.CopyOnWriteArrayList; + +@Service +public class VehicleServiceImpl implements VehicleService { + + protected Logger log = LoggerFactory.getLogger(VehicleServiceImpl.class); + + private static final String RES_STATUS_CODE = "StatusCode"; + private static final String RES_MESSAGE = "Message"; + + @Resource + private LinkVWACService linkVWACService; + + @Resource + private LinkDTService linkDTService; + + @Override + public List getVidList(VehicleParamsDTO dto) { + List vehicleReturnDTOList = new CopyOnWriteArrayList<>(); + List vinList = dto.getVinList(); + try { + List> initThreads = new ArrayList<>(); + for (String vin : vinList) { + Callable callable = () -> { + Object result = linkVWACService.getVIDByVIN(vin); + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + VehicleReturnDTO vehicleReturnDTO = new VehicleReturnDTO(); + if (vidJSONObject.containsKey(RES_STATUS_CODE)) { + vehicleReturnDTO.setVin(vin); + vehicleReturnDTO.setStatusCode(vidJSONObject.getString(RES_STATUS_CODE)); + vehicleReturnDTO.setMessage("[VW.AC]" + vidJSONObject.getString(RES_MESSAGE)); + } else { + vehicleReturnDTO.setVin(vidJSONObject.getString("VehicleUuid")); + vehicleReturnDTO.setVid(vidJSONObject.getString("VehicleId")); + } + vehicleReturnDTOList.add(vehicleReturnDTO); + return true; + }; + initThreads.add(callable); + } + AntThreadPoolUtil.addThread(initThreads); + return vehicleReturnDTOList; + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException("VW.AC interface concurrent call(/vehicles/api/registration/vehicle/vehicleUuid) error: " + ex.getMessage(), HttpStatus.CONFLICT); + } + } + + @Override + public List getVinList(VehicleParamsDTO dto) { + List vehicleReturnDTOList = new CopyOnWriteArrayList<>(); + List vidList = dto.getVidList(); + try { + List> initThreads = new ArrayList<>(); + for (String vid : vidList) { + Callable callable = () -> { + Object result = linkVWACService.getVINByVID(vid); + JSONObject vidJSONObject = JSON.parseObject(result.toString()); + VehicleReturnDTO vehicleReturnDTO = new VehicleReturnDTO(); + vehicleReturnDTO.setVid(vid); + if (vidJSONObject.containsKey(RES_STATUS_CODE)) { + vehicleReturnDTO.setStatusCode(vidJSONObject.getString(RES_STATUS_CODE)); + vehicleReturnDTO.setMessage("[VW.AC]" + vidJSONObject.getString(RES_MESSAGE)); + } else { + vehicleReturnDTO.setVin(vidJSONObject.getString("VehicleUuid")); + } + vehicleReturnDTOList.add(vehicleReturnDTO); + return true; + }; + initThreads.add(callable); + } + AntThreadPoolUtil.addThread(initThreads); + return vehicleReturnDTOList; + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException("VW.AC interface concurrent call(/vehicles/api/registration/vehicle/{vid}/uuid) error: " + ex.getMessage(), HttpStatus.CONFLICT); + } + } + + @Override + public List getVehicleInfoList(VehicleParamsDTO dto) { + List vehicleReturnDTOList = new CopyOnWriteArrayList<>(); + List vidList = dto.getVidList(); + try { + List> initThreads = new ArrayList<>(); + for (String vid : vidList) { + Callable callable = () -> { + Object result = linkDTService.getVehicleInfo(vid); + VehicleReturnDTO vehicleReturnDTO = new VehicleReturnDTO(); + if (ObjectUtils.isEmpty(result)) { + vehicleReturnDTO.setVid(vid); + vehicleReturnDTO.setInfos(new JSONObject().toJSONString()); + vehicleReturnDTOList.add(vehicleReturnDTO); + } else { + vehicleReturnDTOList.add(assembleVehicle(vehicleReturnDTO, result, vid)); + } + return true; + }; + initThreads.add(callable); + } + AntThreadPoolUtil.addThread(initThreads); + return vehicleReturnDTOList; + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new MdmdsException("DT interface concurrent call(/state-api/vehicles/{vid}/state) error: " + ex.getMessage(), HttpStatus.CONFLICT); + } + } + + private VehicleReturnDTO assembleVehicle(VehicleReturnDTO vehicleReturnDTO, Object result, String vid) { + JSONObject stateJSONObject = JSON.parseObject(result.toString()); + JSONObject vehicleJSONObject = stateJSONObject.getJSONObject("state"); + JSONObject infoNewJSONObject = new JSONObject(); + Set keyList = vehicleJSONObject.keySet(); + for (String key : keyList) { + JSONObject valueJSONObject = vehicleJSONObject.getJSONObject(key); + if (valueJSONObject.containsKey("value")) { + infoNewJSONObject.put(key, valueJSONObject.getString("value")); + } + } + vehicleReturnDTO.setVid(vid); + vehicleReturnDTO.setInfos(infoNewJSONObject.toJSONString()); + vehicleReturnDTO.setResult(result.toString()); + return vehicleReturnDTO; + } + + @Override + public String getVehicleFieldValuesByName(String name) { + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("key", name); + try { + Object result = linkDTService.getAllEnumForAttribute(params); + JSONArray dtAttrsValues = JSON.parseArray(result.toString()); + JSONArray dbAttrsValues = new JSONArray(); + for (int idx = 0; idx < dtAttrsValues.size(); idx++) { + String attrValue = dtAttrsValues.getString(idx); + if (attrValue != null) { + dbAttrsValues.add(attrValue); + } + } + return dbAttrsValues.toJSONString(); + } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) { + throw new MdmdsException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new MdmdsException(ie.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + +} diff --git a/src/main/java/com/volkswagen/mdmds/timer/CoreTimer.java b/src/main/java/com/volkswagen/mdmds/timer/CoreTimer.java new file mode 100644 index 0000000..e020a66 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/timer/CoreTimer.java @@ -0,0 +1,51 @@ +package com.volkswagen.mdmds.timer; + +import com.volkswagen.mdmds.constant.CommonField; +import com.volkswagen.mdmds.service.*; +import com.volkswagen.mdmds.utils.TokenUtil; +import jakarta.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.Instant; + +import static com.volkswagen.mdmds.config.JwtAuthenticationFilter.blackTokenMap; + +@Component +public class CoreTimer { + + protected Logger log = LoggerFactory.getLogger(CoreTimer.class); + + @Resource + private AttributeService attributeService; + + /** + * 每隔30分钟清理Token,DT和VW.AC的Token有效时间是1小时 + */ + @Scheduled(cron = "0 0/30 * * * ? ") + public void manageToken() { + if(TokenUtil.containToken(CommonField.DT_TOKEN)) { + TokenUtil.removeValue(CommonField.DT_TOKEN); + } + if(TokenUtil.containToken(CommonField.VWAC_TOKEN)) { + TokenUtil.removeValue(CommonField.VWAC_TOKEN); + } + if(TokenUtil.containToken(CommonField.HW_TOKEN)) { + TokenUtil.removeValue(CommonField.HW_TOKEN); + } + if(TokenUtil.containToken(CommonField.MS_TOKEN)) { + TokenUtil.removeValue(CommonField.MS_TOKEN); + } + // 清理黑名单token + Instant now = Instant.now(); + blackTokenMap.entrySet().removeIf(entry -> entry.getValue().isBefore(now)); + } + +// @Scheduled(cron = "0 0/5 * * * ?") + public void syncDTVehicle() { + attributeService.syncVehicleKeyAndValue(); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/AntStrUtil.java b/src/main/java/com/volkswagen/mdmds/utils/AntStrUtil.java new file mode 100644 index 0000000..2a389ba --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/AntStrUtil.java @@ -0,0 +1,44 @@ +package com.volkswagen.mdmds.utils; + +import com.alibaba.fastjson.JSON; +import io.micrometer.common.util.StringUtils; + +public class AntStrUtil { + private AntStrUtil() { + } + + public static boolean isJSONObject(String content) { + if(StringUtils.isBlank(content)) { + return false; + } + try { + JSON.parseObject(content); + return true; + } catch (Exception e) { + return false; + } + } + + public static boolean isJSONArray(String content) { + if(StringUtils.isBlank(content)) { + return false; + } + try { + JSON.parseArray(content); + return true; + } catch (Exception e) { + return false; + } + } + + public static boolean isVIN(String vin) { +// if(vin.length() == 17 && vin.matches(".*[A-Z].*") && vin.matches(".*[0-9].*")) { +// return true; +// } + if(vin.matches("^(?=.*[0-9])(?=.*[A-Z]).{17}$")){ + return true; + } + return false; + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/AntThreadPoolUtil.java b/src/main/java/com/volkswagen/mdmds/utils/AntThreadPoolUtil.java new file mode 100644 index 0000000..93c2def --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/AntThreadPoolUtil.java @@ -0,0 +1,21 @@ +package com.volkswagen.mdmds.utils; + +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class AntThreadPoolUtil { + + private static ExecutorService executorService = Executors.newFixedThreadPool(100); + + private AntThreadPoolUtil() { + + } + + public static List> addThread(List> threadList) throws InterruptedException { + return executorService.invokeAll(threadList); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/AuditorAwareImpl.java b/src/main/java/com/volkswagen/mdmds/utils/AuditorAwareImpl.java new file mode 100644 index 0000000..7d0ae76 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/AuditorAwareImpl.java @@ -0,0 +1,34 @@ +package com.volkswagen.mdmds.utils; + +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.Jwt; + +import java.util.Optional; + +/** + * @author Shuo Ding + * @since 2023/2/8 + * 提供DATA JPA用于audit,获取当前用户信息的 + */ +public class AuditorAwareImpl implements AuditorAware { + + @Override + public Optional getCurrentAuditor() { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if(null != authentication) { + Object principal = authentication.getPrincipal(); + if(principal instanceof Jwt user) { + user = (Jwt) principal; + return Optional.of(user.getClaims().getOrDefault("name","EHRM").toString()); + } else { + return Optional.of("MDMDS"); + } + } else { + return Optional.of("SYS"); + } + + } +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/ExcelUtil.java b/src/main/java/com/volkswagen/mdmds/utils/ExcelUtil.java new file mode 100644 index 0000000..9f09c4e --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/ExcelUtil.java @@ -0,0 +1,404 @@ +package com.volkswagen.mdmds.utils; + +import com.alibaba.excel.util.StringUtils; +import com.google.common.collect.Lists; +import com.volkswagen.mdmds.config.exception.MdmdsException; +import com.volkswagen.mdmds.model.excel.VehicleAttributeAdapterField; +import com.volkswagen.mdmds.utils.annotation.ExcelField; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * excel工具类 + * Created by Administrator on 2018/9/25. + */ +public class ExcelUtil { + private static Logger logger = LoggerFactory.getLogger(ExcelUtil.class); + + private ExcelUtil() { + + } + + /** + * 通过实体类创建Excel模板 + * @param response 相应 + * @param clazz 实体类 + * @param fileName 文件名 + * @param excludeColumnNames 过滤的字段 + * @throws IOException + */ + public static void createExcelTemplate(HttpServletResponse response, Class clazz, String fileName , Set excludeColumnNames) throws IOException { + getExcelTemplate(response, clazz, fileName,true, excludeColumnNames); + } + + private static void getExcelTemplate(HttpServletResponse response, + Class clzz, String fileName, boolean flag, Set excludeColumnNames + ) throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook(); OutputStream out = response.getOutputStream()){ + createSheet(clzz, fileName, flag, excludeColumnNames, wb); + createSheet(VehicleAttributeAdapterField.class, "Mapping Sheet", flag, excludeColumnNames, wb); + response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + wb.write(out); + } + + } + + private static void createSheet(Class clzz, String fileName, boolean flag, Set excludeColumnNames, XSSFWorkbook wb) { + XSSFSheet sheet = wb.createSheet(fileName); + String[] headers = getSortedExcelHeaders(clzz, flag); + Row headerRow = sheet.createRow(0); + int delta = 0; + for(int i = 0; i < headers.length; i++) { + if(excludeColumnNames != null && !excludeColumnNames.isEmpty() && excludeColumnNames.contains(headers[i])) { + delta++; + continue; + } + headerRow.createCell(i-delta).setCellValue(headers[i]); + } + } + + private static String[] getSortedExcelHeaders(Class clzz, boolean flag) { + ArrayList headerList = new ArrayList<>(); + HashMap map = new HashMap<>(); + Field[] fields; + if(flag) { + fields = getAllDeclaredFields(clzz); + } else { + fields = clzz.getDeclaredFields(); + } + ExcelField t; + for (Field field : fields) { + //获取属性上T类型的注解 + if(field.isAnnotationPresent(ExcelField.class)) { + t = field.getAnnotation(ExcelField.class); + if(t.importIgnore()){ + continue; + } + map.put(t.name(),t.order()); + } + } + List> list = new ArrayList<>(map.entrySet()); + Collections.sort(list,Comparator.comparingInt(Map.Entry::getValue)); + for(Map.Entry entry:list){ + headerList.add(entry.getKey()); + } + return headerList.toArray(new String[headerList.size()]); + } + + public static List readFile(MultipartFile file, Class clzz) { + return readFile(file, clzz, "name", 0); + } + + public static List readFile(MultipartFile file, Class clzz, int readSheet) { + return readFile(file, clzz, "name", readSheet); + } + + private static List readFile(MultipartFile file, Class clzz, String methodName, int readSheet) { + Workbook wb = null; + try { + if (file == null || !validateExcel(file.getOriginalFilename())) { + return Lists.newArrayList(); + } + InputStream is; + is = file.getInputStream(); + String filename = file.getOriginalFilename(); + if(filename == null) { + throw new MdmdsException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), HttpStatus.INTERNAL_SERVER_ERROR); + } + //创建工作表 + if (isExcel2003(filename)) { + wb = new HSSFWorkbook(is); + } else { + wb = new XSSFWorkbook(is); + } + return readExcel(clzz, wb, methodName, readSheet); + } catch (IOException e) { + return Lists.newArrayList(); + } + } + + /** + * 读取Excel内容,默认第一行为标题行 + */ + private static List readExcel(Class clzz, Workbook wb, String methodName, int readSheet) { + List list = new ArrayList<>(); + //获取实体类的所有属性 + Field[] fields = getAllDeclaredFields(clzz); + + if(fields==null){ + return list; + } + + HashMap map = getFieldMap(fields, methodName); + Sheet sheet = wb.getSheetAt(readSheet); + Row title = sheet.getRow(0); + int totalColumns = title.getPhysicalNumberOfCells(); + int totalRows = sheet.getLastRowNum(); + //获取Excel所有的列标题 + String[] titles = getColumnTitle(title, totalColumns); + Cell cell; + Row row; + E e; + //从第二行开始读取数据 + for (int i = 1; i <= totalRows; i++) { + row = sheet.getRow(i); + if(null == row) { + throw new MdmdsException("There is a null row in the " + (i + 1) + " row", HttpStatus.CONFLICT); + } + e = getNewInstance(clzz); + for (int j = 0; j < totalColumns; j++) { + cell = row.getCell(j); + if(map.get(titles[j])!=null){ + readCellContent(map.get(titles[j]), fields, cell, e); + } + } + list.add(e); + } + return list; + + } + + private static Field[] getAllDeclaredFields(Class clzz){ + Field[] fields = null; + while(clzz != null){ + Field[] fs = clzz.getDeclaredFields(); + fields = ArrayUtils.addAll(fields,fs); + clzz = clzz.getSuperclass(); + } + return fields; + } + + /** + * 读取单元格内容,并将内容添加到实体类E中 + * @param fieldName 当前单元格对应的Bean字段 + * @param fields 属性数组 + * @param cell 单元格 + * @param e 实体类 + */ + private static void readCellContent(String fieldName, Field[] fields, Cell cell, E e) { + Object obj = getCellValue(cell); + if (obj == null) { + return; + } + mappingValueToBean(fieldName, fields, obj, e); + } + + /** + * 映射值到实体类 + * @param fieldName + * @param fields + * @param obj + * @param e + */ + private static void mappingValueToBean(String fieldName, Field[] fields, Object obj, E e) { + try { + for (Field field : fields) { + if(fieldName.equals(field.getName())) { + //设置私有属性可以访问 + field.setAccessible(true); + + field.set(e, getValue(field, obj)); + break; + } + } + } catch (IllegalArgumentException | IllegalAccessException e1) { + logger.error("{}", e1.getMessage()); + } + } + + /** + * 获取列标题 + * @param title 列标题所在行 + * @param totalColumns 总列数 + * @return String[] + */ + private static String[] getColumnTitle(Row title, int totalColumns) { + String[] titles = new String[totalColumns]; + for (int j = 0; j < totalColumns; j++) { + Cell cell = title.getCell(j); + if(cell!=null){ + titles[j] = cell.getStringCellValue(); + }else{ + break; + } + } + return titles; + } + + /** + * 获取属性和注解对应的集合 + * @param fields + * @param methodName + * @return Map : key为属性上的注解值,value为属性名 + */ + private static HashMap getFieldMap(Field[] fields, String methodName) { + HashMap map = new HashMap<>(); + ExcelField t; + for (Field field : fields) { + //获取属性上T类型的注解 + if(field.isAnnotationPresent(ExcelField.class)) { + t = field.getAnnotation(ExcelField.class); + if (!t.importIgnore()) { + map.put(String.valueOf(getMethodReturnValue(t, methodName)), field.getName()); + } + } + } + return map; + } + + /** + * 获取方法的返回值 + * @param t 实体类 + * @param methodName 方法名 + * @return Object + */ + private static Object getMethodReturnValue(T t, String methodName) { + Object obj = null; + try { + obj = t.getClass().getMethod(methodName).invoke(t); + } catch (NoSuchMethodException | IllegalArgumentException | SecurityException | IllegalAccessException | + InvocationTargetException e) { + logger.error("{}", e.getMessage()); + } + return obj; + } + + /** + * 获取单元格的值 + * @param cell + * @return Object + */ + private static Object getCellValue(Cell cell) { + Object obj; + if(cell == null){ + obj = StringUtils.EMPTY; + return obj; + } + // 以下是判断数据的类型 + switch (cell.getCellTypeEnum()) { + case NUMERIC : // 数字 + obj = cell.getNumericCellValue(); + break; + case STRING : // 字符串 + obj = cell.getStringCellValue().trim(); + break; + case BOOLEAN : // Boolean + obj = cell.getBooleanCellValue(); + break; + case FORMULA : // 公式 + obj = cell.getStringCellValue().trim(); + break; + case BLANK : // 空值 + obj = StringUtils.EMPTY; + break; + case ERROR : // 故障 + obj = "非法字符"; + break; + default: + obj = "未知类型"; + break; + } + return obj; + } + + /** + * 将obj的值转化为该属性类型的值 + * @param field + * @param obj + * @return + */ + private static Object getValue(Field field, Object obj) { + if(field.getType().equals(obj.getClass())) { + return obj; + } + Object obj2 = null; + try { + if(Date.class.equals(field.getType())) { + obj2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(obj.toString()); + }else if (String.class.equals(field.getType())) { + obj2 = String.valueOf(obj).trim(); + }else if (Long.class.equals(field.getType())) { + obj2 = Long.valueOf(obj.toString()); + }else if (Integer.class.equals(field.getType())) { + obj2 = Integer.valueOf(obj.toString()); + }else if (BigDecimal.class.equals(field.getType())) { + obj2 = new BigDecimal(obj.toString()); + }else if (Boolean.class.equals(field.getType())) { + obj2 = Boolean.valueOf(obj.toString()); + }else if (Float.class.equals(field.getType())) { + obj2 = Float.valueOf(obj.toString()); + }else if (Double.class.equals(field.getType())) { + obj2 = Double.valueOf(obj.toString()); + } + } catch (ParseException e) { + logger.error("{}", e.getMessage()); + } + return obj2; + } + + + /** + * 验证是否是Excel格式的文件 + * @param fileName:文件名 + * @return boolean : true表示是Excel格式的文件,false表示不是 + */ + private static boolean validateExcel(String fileName) { + return !(fileName == null || !(isExcel2003(fileName) || isExcel2007(fileName))); + } + + /** + * 判断是不是2003格式的Excel + * @param fileName + * @return boolean : true表示是2003格式的Excel,false表示不是 + */ + private static boolean isExcel2003(String fileName) { + return fileName.matches("^.+\\.(?i)(xls)$"); + } + + /** + * 判断是不是2007格式的Excel + * @param fileName + * @return boolean : true表示是2007格式的Excel,false表示不是 + */ + private static boolean isExcel2007(String fileName) { + return fileName.matches("^.+\\.(?i)(xlsx)$"); + } + + /** + * 通过反射获取T类的新实例 + * @param clzz + * @return T + */ + private static T getNewInstance(Class clzz) { + T t = null; + try { + t = clzz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + logger.error("{}", e.getMessage()); + } + return t; + } + + public static void main(String[] args) { + + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/IPUtil.java b/src/main/java/com/volkswagen/mdmds/utils/IPUtil.java new file mode 100644 index 0000000..ebd2aa1 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/IPUtil.java @@ -0,0 +1,249 @@ +package com.volkswagen.mdmds.utils; + +import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class IPUtil { + + private static Logger logger = LoggerFactory.getLogger(IPUtil.class); + + private IPUtil() { + + } + + private static final String UNKNOWN = "unknown"; + + /** + * 默认IP地址 + */ + public static final String ERROR_IP = "127.0.0.1"; + + /** + * IP地址正则表达式 + */ + public static final Pattern pattern = Pattern.compile( + "(2[5][0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})"); + + /** + * + * @title isValidIP + * @description 根据请求验证IP地址 + * @param request + * @return boolean + * + */ + public static boolean isValidIP(HttpServletRequest request) + { + // 获取用户真实的IP地址 + String ip = getUserIP(request); + // 验证IP地址是否符合规则 + return isValidIP(ip); + } + + /** + * + * @title getRemoteIp + * @description 获取远程IP地址 + * @param request + * @return String + * + */ + public static String getRemoteIp(HttpServletRequest request) + { + String ip = request.getHeader("x-real-ip"); + if (ip == null) + { + ip = request.getRemoteAddr(); + } + // 过滤反向代理的ip + String[] stemps = ip.split(","); + if (stemps != null && stemps.length >= 1) + { + // 得到第一个IP,即客户端真实IP + ip = stemps[0]; + } + + ip = ip.trim(); + if (ip.length() > 23) + { + ip = ip.substring(0, 23); + } + + return ip; + } + + /** + * + * @title getUserIP + * @description 获取用户真实的IP地址 + * @param request + * @return String + * + */ + public static String getUserIP(HttpServletRequest request) { + // 优先取 X-Real-IP + String ip = request.getHeader("X-Real-IP"); + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("x-forwarded-for"); + } + + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + if ("0:0:0:0:0:0:0:1".equals(ip)) { + ip = ERROR_IP; + } + } + if (UNKNOWN.equalsIgnoreCase(ip)) { + ip = ERROR_IP; + return ip; + } + int index = ip.indexOf(','); + if (index >= 0) { + ip = ip.substring(0, index); + } + + return ip; + } + + /** + * + * @title getLastIpSegment + * @description 获取末尾IP地址段 + * @param request + * @return String + * + */ + public static String getLastIpSegment(HttpServletRequest request) + { + // 获取用户真实的IP地址 + String ip = getUserIP(request); + if (ip != null) + { + ip = ip.substring(ip.lastIndexOf('.') + 1); + } else + { + ip = "0"; + } + return ip; + } + + /** + * + * @title isValidIP + * @description 验证IP地址是否符合规则 + * @param ip + * @return boolean + * + */ + public static boolean isValidIP(String ip) + { + if (StringUtils.isEmpty(ip)) + { + return false; + } + Matcher matcher = pattern.matcher(ip); + return matcher.matches(); + } + + /** + * + * @title getLastServerIpSegment + * @description 获取服务器的会后一个地址段 + * @return String + * + */ + public static String getLastServerIpSegment() + { + String ip = getServerIP(); + if (ip != null) + { + ip = ip.substring(ip.lastIndexOf('.') + 1); + } else + { + ip = "0"; + } + return ip; + } + + /** + * + * @title getServerIP + * @description 获取服务器IP地址 + * @return String + * + */ + public static String getServerIP() { + InetAddress inetAddress; + try { + inetAddress = InetAddress.getLocalHost(); + return inetAddress.getHostAddress(); + } catch (UnknownHostException e) { + logger.error(e.getMessage()); + } + return ERROR_IP; + } + + /** + * + * @title getIpAddress + * @description + *
  • 获取IP地址 + *
  • 注意:IP地址经过多次反向代理后会有多个IP值, + *
  • 其中第一个IP才是真实IP,所以不能通过request.getRemoteAddr()获取IP地址, + *
  • 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址, + *
  • X-Forwarded-For中第一个非unknown的有效IP才是用户真实IP地址。 + * + * @param request + * @return String + * + */ + public static String getIpAddress(HttpServletRequest request) { + String ip = null; + try { + // 获取用户真是的地址 + String xIP = request.getHeader("X-Real-IP"); + // 获取多次代理后的IP字符串值 + String xFor = request.getHeader("X-Forwarded-For"); + if (StringUtils.isNotEmpty(xFor) && !UNKNOWN.equalsIgnoreCase(xFor)) { + // 多次反向代理后会有多个IP值,第一个用户真实的IP地址 + int index = xFor.indexOf(","); + if (index >= 0) { + return xFor.substring(0, index); + } else { + return xFor; + } + } + ip = xIP; + return getIPByHeader(request, ip); + } catch (Exception e) { + logger.error(e.getMessage()); + } + return ip; + } + + private static String getIPByHeader(HttpServletRequest request, String ip) { + if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (StringUtils.isEmpty(ip) || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/MyHttpClient.java b/src/main/java/com/volkswagen/mdmds/utils/MyHttpClient.java new file mode 100644 index 0000000..d560147 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/MyHttpClient.java @@ -0,0 +1,34 @@ +package com.volkswagen.mdmds.utils; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.TrustManager; +import java.net.http.HttpClient; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.time.Duration; + +public class MyHttpClient { + + private MyHttpClient() { + + } + + public static HttpClient.Builder getClient() throws NoSuchAlgorithmException, KeyManagementException { + TrustManager[] trustManagers = MyX509TrustManager.getTrustManagers(); + var timeoutInSeconds = 60; + SSLParameters sslParams = new SSLParameters(); + sslParams.setEndpointIdentificationAlgorithm(""); + SSLContext sc = SSLContext.getInstance("TLSv1.2");// SSL,TLSv1.2,TLSv1.3 + //取消主机名验证 + System.setProperty("jdk.internal.httpclient.disableHostnameVerification", "true"); + sc.init(null, trustManagers, new SecureRandom()); + return HttpClient.newBuilder() + .connectTimeout(Duration.ofMillis(timeoutInSeconds * 1000l)) + .sslContext(sc) + .sslParameters(sslParams) + .followRedirects(HttpClient.Redirect.NEVER) + .version(HttpClient.Version.HTTP_2); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/MyX509TrustManager.java b/src/main/java/com/volkswagen/mdmds/utils/MyX509TrustManager.java new file mode 100644 index 0000000..e571649 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/MyX509TrustManager.java @@ -0,0 +1,40 @@ +package com.volkswagen.mdmds.utils; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +public class MyX509TrustManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // Do nothing. Just allow them all. + try { + chain[0].checkValidity(); + } catch (Exception e) { + throw new CertificateException("Certificate not valid or trusted."); + } + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // Do nothing. Just allow them all. + try { + chain[0].checkValidity(); + } catch (Exception e) { + throw new CertificateException("Certificate not valid or trusted."); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { +// return new X509Certificate[0]; + return null; // Not relevant. + } + + public static TrustManager[] getTrustManagers() { + TrustManager[] trustAllCertificates = {new MyX509TrustManager()}; + return trustAllCertificates; + } +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/TokenUtil.java b/src/main/java/com/volkswagen/mdmds/utils/TokenUtil.java new file mode 100644 index 0000000..a72ea47 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/TokenUtil.java @@ -0,0 +1,49 @@ +package com.volkswagen.mdmds.utils; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class TokenUtil { + + private static final Map tokenMap = new ConcurrentHashMap<>(); + + private TokenUtil() { + + } + + /** + * 是否含有token + * @param key + * @return + */ + public static boolean containToken(String key) { + return tokenMap.containsKey(key); + } + + /** + * + * @param key + * @param value + */ + public static void setValue(String key, String value) { + tokenMap.put(key, value); + } + + /** + * + * @param key + * @return + */ + public static String getValue(String key) { + return tokenMap.get(key); + } + + /** + * + * @param key + */ + public static void removeValue(String key) { + tokenMap.remove(key); + } + +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/ToolUtil.java b/src/main/java/com/volkswagen/mdmds/utils/ToolUtil.java new file mode 100644 index 0000000..c6e31e8 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/ToolUtil.java @@ -0,0 +1,23 @@ +package com.volkswagen.mdmds.utils; + +/** + * @author Shuo Ding + * @since 2023/3/16 + */ +public class ToolUtil { + + private ToolUtil() { + + } + + /** + * 校验字符串,只能包含中英文字符和数字 + * + * @param str + * @return + */ + public static boolean isLetterDigitOrChinese(String str) { + String regex = "^[a-z0-9A-Z\u4e00-\u9fa5]+$"; + return str.matches(regex); + } +} diff --git a/src/main/java/com/volkswagen/mdmds/utils/annotation/ExcelField.java b/src/main/java/com/volkswagen/mdmds/utils/annotation/ExcelField.java new file mode 100644 index 0000000..21a9a21 --- /dev/null +++ b/src/main/java/com/volkswagen/mdmds/utils/annotation/ExcelField.java @@ -0,0 +1,17 @@ +package com.volkswagen.mdmds.utils.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.METHOD, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelField { + // 列名 + String name() default ""; + // 导出列的顺序 + int order() default 999; + + boolean importIgnore() default false; +} diff --git a/src/main/proto/version.proto b/src/main/proto/version.proto new file mode 100644 index 0000000..0f7dcf5 --- /dev/null +++ b/src/main/proto/version.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +option java_package = "com.volkswagen.mdmds.protobuf"; + +option java_outer_classname = "VersionBuf"; + +message Version { + string adsVersion=1; + string shadowVersion=2; + string vwVersion=3; + } \ No newline at end of file diff --git a/src/main/resources/application-apr.yaml b/src/main/resources/application-apr.yaml new file mode 100644 index 0000000..e3df78e --- /dev/null +++ b/src/main/resources/application-apr.yaml @@ -0,0 +1,80 @@ +spring: + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hibernate: + ddl-auto: update + show-sql: 'true' + datasource: + # driver-class-name: org.postgresql.Driver + password: Tsystems2024 + username: mdmds-user + url: jdbc:postgresql://74.48.68.125:5432/mdmds-bs?createDatabaseIfNotExist=true&useSSL=true&characterEncoding=UTF-8&stringtype=unspecified + application: + name: EHR_BACKEND_PROD + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://auth.haramasu.com/auth/realms/testmdmds + kafka: + bootstrap-servers: "kafka-pub.tui.dts.vwautocloud.cn:32550" + topics: + version-topic: EVENTSTATUIS-CADA-AUDI-APPR + groups: + version-group: mirrormaker-mdmds + consumer: + enable-auto-commit: false + auto-offset-reset: earliest + properties: + ssl: + endpoint: + identification: + algorithm: "" + ssl: + key-store-location: "classpath:kafka_client.p12" + key-store-password: C9&JtU@H3$tRd$ + key-store-type: PKCS12 + trust-store-location: "classpath:kafka_client.pem" + trust-store-type: PEM + protocol: SSL + properties: + security: + protocol: SASL_SSL + sasl: + mechanism: SCRAM-SHA-256 + jaas: + config: org.apache.kafka.common.security.scram.ScramLoginModule required username="ddsmeta" password="ddsmeta"; + +jwt: + auth: + converter: + #表示允许通过校验的CLIENT_ID + resource-id: EHR_FRONTEND_PROD + principal-attribute: preferred_username + unique-attribute: deviceId + +dt-api: + url: paas-apr-china.apr.digitaltwin.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: 35e05719-52e6-4a56-a835-f5e29ea64d5d + client_secret: L~cm~w.S3w8.mEfFUG0Hsm1xnKwGsWA0HK + scope: api://88642b27-0282-4448-a62c-feb725727e62/.default + grant_type: client_credentials +vwac-api: + url: apr-vwacv-a72-apim.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: 35e05719-52e6-4a56-a835-f5e29ea64d5d + client_secret: 7ycjlB3.d8G8kmIMWR..BB7u~6Q_sEXD~. + scope: api://china-apr-vwacv-a72-apim-backend-sp/.default + grant_type: client_credentials +hw-api: + url: open-ops.preprod.adscloud.huawei.com + oauth_url: open-ops.preprod.adscloud.huawei.com/viam/v1/auth/apptoken + client_id: 36 + client_secret: rfkSTMjMElGn8lnLu1hbt0x8BMSwzdHO + grant_type: client_credentials + scopes: adscloud_ddi_app_external_mdmds diff --git a/src/main/resources/application-live.yaml b/src/main/resources/application-live.yaml new file mode 100644 index 0000000..3c69b56 --- /dev/null +++ b/src/main/resources/application-live.yaml @@ -0,0 +1,80 @@ +spring: + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hibernate: + ddl-auto: update + show-sql: 'true' + datasource: + # driver-class-name: org.postgresql.Driver + password: Tsystems2024 + username: mdmds-user + url: jdbc:postgresql://74.48.68.125:5432/mdmds-bs?createDatabaseIfNotExist=true&useSSL=true&characterEncoding=UTF-8&stringtype=unspecified + application: + name: EHR_BACKEND_PROD + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://auth.haramasu.com/auth/realms/testmdmds + kafka: + bootstrap-servers: "kafka-pub.prod.dts.vwautocloud.cn:33850" + topics: + version-topic: EVENTSTATUS-CADA-AUDI-PROD + groups: + version-group: mirrormaker-mdmds-prod + consumer: + enable-auto-commit: false + auto-offset-reset: earliest + properties: + ssl: + endpoint: + identification: + algorithm: "" + ssl: + key-store-location: "classpath:kafka_client.p12" + key-store-password: C9&JtU@H3$tRd$ + key-store-type: PKCS12 + trust-store-location: "classpath:kafka_client.pem" + trust-store-type: PEM + protocol: SSL + properties: + security: + protocol: SASL_SSL + sasl: + mechanism: SCRAM-SHA-256 + jaas: + config: org.apache.kafka.common.security.scram.ScramLoginModule required username="audiprod" password="&audiprod0338@!"; + +jwt: + auth: + converter: + #表示允许通过校验的CLIENT_ID + resource-id: EHR_FRONTEND_PROD + principal-attribute: preferred_username + unique-attribute: deviceId + +dt-api: + url: paas-live-china.live.digitaltwin.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: ebb67f2e-9802-493a-b2a7-6fda687a8c14 + client_secret: _-NSY.3X9Jp983gDeg13dI~y_EM9saBm8e + scope: api://7ff62620-7f6b-4c14-83ee-f696fb2dfe4c/.default + grant_type: client_credentials +vwac-api: + url: ipr-vwacv-ea7-apim.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: ebb67f2e-9802-493a-b2a7-6fda687a8c14 + client_secret: _-NSY.3X9Jp983gDeg13dI~y_EM9saBm8e + scope: api://china-ipr-vwacv-ea7-apim-backend-sp/.default + grant_type: client_credentials +hw-api: + url: open-ops.adscloud.huawei.com + oauth_url: open-ops.adscloud.huawei.com/viam/v1/auth/apptoken + client_id: 36 + client_secret: uukRl9MfwJI57enPiVLX9e1nYrkqpgV2 + grant_type: client_credentials + scopes: adscloud_ddi_app_external_mdmds \ No newline at end of file diff --git a/src/main/resources/application-uat_delete.yaml b/src/main/resources/application-uat_delete.yaml new file mode 100644 index 0000000..694bb9a --- /dev/null +++ b/src/main/resources/application-uat_delete.yaml @@ -0,0 +1,52 @@ +spring: + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hibernate: + ddl-auto: update + show-sql: 'true' + datasource: + password: EHR_2021_tsystems + # driver-class-name: org.mariadb.jdbc.Driver + # driver-class-name: org.postgresql.Driver + username: dbop + url: jdbc:postgresql://mdmdscenterpg.postgres.database.chinacloudapi.cn:5432/mdmds?createDatabaseIfNotExist=true&useSSL=true&characterEncoding=UTF-8&stringtype=unspecified + application: + name: MDMDS-BS-PROD + security: + oauth2: + resourceserver: + jwt: + issuer-uri: https://idp.qs.cloudidp.vgcserv.com.cn/auth/realms/vgcmfa + +jwt: + auth: + converter: + #表示允许通过校验的CLIENT_ID + resource-id: EHR_FRONTEND_QS + principal-attribute: preferred_username + +dt-api: + url: paas-apr-china.apr.digitaltwin.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: 35e05719-52e6-4a56-a835-f5e29ea64d5d + client_secret: 7ycjlB3.d8G8kmIMWR..BB7u~6Q_sEXD~. + scope: api://88642b27-0282-4448-a62c-feb725727e62/.default + grant_type: client_credentials +vwac-api: + url: apr-vwacv-a72-apim.vwcloud.cn + oauth_url: login.partner.microsoftonline.cn/a12a82ff-eb68-4d6d-b3c7-c4fb2d2220e5/oauth2/v2.0/token + auth_type: BearerToken + client_id: 35e05719-52e6-4a56-a835-f5e29ea64d5d + client_secret: 7ycjlB3.d8G8kmIMWR..BB7u~6Q_sEXD~. + scope: api://china-apr-vwacv-a72-apim-backend-sp/.default + grant_type: client_credentials +hw-api: + url: api.lbeta.adscloud.huawei.com + oauth_url: api.lbeta.adscloud.huawei.com/viam/v1/auth/apptoken + client_id: 30 + client_secret: NgoTAV7A3m2ovAVUttb4523Ict9zTV3Z + grant_type: client_credentials + scopes: adscloud_ddi_app_external_mdmds \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..1d04d42 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,84 @@ +server: + port: 8081 +spring: + application: + name: MDMDS-BS-PROD + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hibernate: + ddl-auto: update + show-sql: false + datasource: + url: ${DB_CONNECT_STR} + username: ${DB_USER} + password: ${DB_PWD} + security: + oauth2: + resourceserver: + jwt: + issuer-uri: ${IDP_URI} + kafka: + bootstrap-servers: ${KAFKA_SERVER} + topics: + version-topic: ${KAFKA_VERSION_TOPIC} + groups: + version-group: ${KAFKA_VERSION_GROUP} + consumer: + enable-auto-commit: false + auto-offset-resetauto-offset-reset: earliest + properties: + ssl: + endpoint: + identification: + algorithm: "" + ssl: + key-store-location: "file:/kafka_client.p12" + key-store-password: ${KAFKA_KEYSTORE_PASSWORD} + key-store-type: PKCS12 + trust-store-location: "file:/kafka_client.pem" + trust-store-type: PEM + protocol: SSL + properties: + security: + protocol: SASL_SSL + sasl: + mechanism: SCRAM-SHA-256 + jaas: + config: org.apache.kafka.common.security.scram.ScramLoginModule required username="${KAFKA_USERNAME}" password="${KAFKA_PASSWORD}"; +# profiles: +# active: apr +#logging: +# config: classpath:bklogback-spring.xml + +jwt: + auth: + converter: + resource-id: ${RES_ID} + principal-attribute: preferred_username + unique-attribute: deviceId + +dt-api: + url: ${API_DT_URL} + oauth_url: ${API_DT_OAUTH_URL} + auth_type: BearerToken + client_id: ${SP_CLIENT_ID} + client_secret: ${SP_CLIENT_SECRET} + grant_type: client_credentials + scope: ${API_DT_SCOPE} +vwac-api: + url: ${API_VWAC_URL} + oauth_url: ${API_VWAC_OAUTH_URL} + auth_type: BearerToken + client_id: ${SP_CLIENT_ID} + client_secret: ${SP_CLIENT_SECRET} + grant_type: client_credentials + scope: ${API_VWAC_SCOPE} +hw-api: + url: ${API_HW_URL} + oauth_url: ${API_HW_OAUTH_URL} + client_id: ${HW_CLIENT_ID} + client_secret: ${HW_CLIENT_SECRET} + grant_type: client_credentials + scopes: ${API_HW_SCOPE} \ No newline at end of file diff --git a/src/main/resources/application_delete.yaml b/src/main/resources/application_delete.yaml new file mode 100644 index 0000000..eb3fcee --- /dev/null +++ b/src/main/resources/application_delete.yaml @@ -0,0 +1,58 @@ +server: + port: 8081 + +#keycloak: +# auth-server-url: https://idp.qs.cloudidp.vgcserv.com.cn/auth +# realm: vgcmfa +# resource: EHR_BACKEND_QS +# credentials: +# secret: 4bb3a67f-1b13-4e40-ab3d-93a3a68f8f2a +# bearer-only: 'true' +# use-resource-role-mappings: 'true' +# ssl-required: external + +spring: + profiles: + active: uat + jpa: + properties: + hibernate: + dialect: ${DB_DIALECT} + hibernate: + ddl-auto: update + show-sql: 'true' + datasource: + password: ${DB_PWD} + driver-class-name: { DB_CLASS } + username: ${DB_USER} + url: ${DB_CONNECT_STR} + application: + name: MDMDS-BS-PROD + security: + oauth2: + resourceserver: + jwt: + issuer-uri: https://idp.qs.cloudidp.vgcserv.com.cn/auth/realms/vgcmfa +# issuer-uri: http://10.25.66.12:65186/auth/realms/mdmds + + + +logging: + config: classpath:logback-spring.xml +# level: +# org.springframework.security: DEBUG + +jwt: + auth: + converter: + #表示允许通过校验的CLIENT_ID + resource-id: EHR_FRONTEND_QS + principal-attribute: preferred_username + +#digital-twin: +# url: paas-apr-china.apr.digitaltwin.vwcloud.cn/digitaltwin-api +# oauth-url: https://paas-apr-china.apr.digitaltwin.vwcloud.cn +# auth-type: basicAuth +#spring.datasource.username=dbop@mdmdscenterdb +#spring.datasource.password=EHR_2021_tsystems +#spring.datasource.url=jdbc:mariadb://mdmdscenterdb.mariadb.database.chinacloudapi.cn:3306/mdmds-test?createDatabaseIfNotExist=true&useSSL=true&?characterEncoding=UTF-8 \ No newline at end of file diff --git a/src/main/resources/bklogback-spring.xml b/src/main/resources/bklogback-spring.xml new file mode 100644 index 0000000..4bf2e3a --- /dev/null +++ b/src/main/resources/bklogback-spring.xml @@ -0,0 +1,75 @@ + + + mdmds + + + + + + + + ${log.pattern} + + + + + + + + ${LOG_HOME}/mdmds.log.%d{yyyy-MM-dd}.log + + + 30 + + + + ${log.pattern} + + + + + 10MB + + + + + + ${LOG_HOME}/error.%d{yyyy-MM-dd}.log + + + + ${log.pattern} + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/dt/key.json b/src/main/resources/dt/key.json new file mode 100644 index 0000000..c17b3af --- /dev/null +++ b/src/main/resources/dt/key.json @@ -0,0 +1,5411 @@ +{ + "keyList": [ + "0K9", + "additionalProp1", + "additionalProp2", + "additionalProp3", + "ads_version", + "api_cso/app-services/bdp/v1/topviewsetup/cameraConfig/set", + "api_cso/app-services/bdp/v1/topviewsetup/cameraProperties", + "api_cso/app-services/bdp/v1/topviewsetup/imageData/trigger", + "api_cso/app-services/bdp/v1/topviewsetup/streamConfig/set", + "api_cso/app-services/bdp/v1/topviewsetup/streamProperties", + "api_cso/app-services/extendedwakingphase/v1/hvNetworkInformation", + "api_cso/app-services/extendedwakingphase/v1/keepConnectOn", + "api_cso/app-services/extendedwakingphase/v1/keepConnectOn/set", + "api_cso/app-services/extendedwakingphase/v1/keepconnecton/switchconfig/set", + "api_cso/app-services/extendedwakingphase/v1/modFollowupTime/set", + "api_cso/app-services/factoryreset/v1/createResource", + "api_cso/app-services/factoryreset/v1/resetstate/set", + "api_cso/app-services/factoryreset/v1/trigger", + "api_cso/app-services/highvoltage/v1/wakelock/acquire", + "api_cso/app-services/highvoltage/v1/wakelock/release", + "api_cso/app-services/hvac/v1/wakelock/acquire", + "api_cso/app-services/hvac/v1/wakelock/release", + "api_cso/app-services/rem/v1/buffered/rsdData", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/activeBackend", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/configDataBackend", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/control/serviceStatus", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/control/serviceStatus/set", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/correctionDataUpdate", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/setGridInfo", + "api_cso/app-services/rtk/v1/gnsscorrectiondata/statusUpdate", + "api_cso/autoedge/v1/tgi/cloudoutput", + "api_cso/autoedge/v1/tgi/cloudoutput/publish", + "api_cso/autoedge/v1/tgi/cloudoutputpublish", + "api_cso/cso/debug/positioncompleteressource", + "api_cso/cso/debug/sol2test", + "api_cso/cso/debug/stub", + "api_cso/cso/debug/TableResultVarTopic/brake", + "api_cso/cso/debug/vehicle/location/detailed/deadReckoning", + "api_cso/cso/debug/vehicle/motion/longitudinal/speed/measured", + "api_cso/cso/v1/autoedge/baselineVersion", + "api_cso/cso/v1/drivingenvironment/cluster/weatherconditions", + "api_cso/cso/v1/drivingenvironment/countryCode", + "api_cso/cso/v1/drivingenvironment/outdoorTemperature", + "api_cso/cso/v1/drivingenvironment/roadattributes/functionalRoadClass", + "api_cso/cso/v1/drivingenvironment/roadattributes/isInsideCity", + "api_cso/cso/v1/drivingenvironment/roadattributes/isUrbanArea", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/currentIndex", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/nbrAcceleration", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/nbrDeceleration", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/rampType", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/totalNumber", + "api_cso/cso/v1/drivingenvironment/roadattributes/laneinformation/totalNumberOpposite", + "api_cso/cso/v1/drivingenvironment/roadattributes/streetClass", + "api_cso/cso/v1/drivingenvironment/time/utc", + "api_cso/cso/v1/drivingenvironment/trafficrules/speedLimit", + "api_cso/cso/v1/drivingenvironment/trafficrules/trafficHandedness", + "api_cso/cso/v1/drivingenvironment/weathercondition/brightness", + "api_cso/cso/v1/drivingenvironment/weathercondition/brightnessforward", + "api_cso/cso/v1/drivingenvironment/weathercondition/dewpoint", + "api_cso/cso/v1/drivingenvironment/weathercondition/humidity", + "api_cso/cso/v1/drivingenvironment/weathercondition/precipitation", + "api_cso/cso/v1/drivingenvironment/weatherconditions", + "api_cso/cso/v1/vehicle/accessmanagement/authorizedKey", + "api_cso/cso/v1/vehicle/accessmanagement/isImmobilizerActivated", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/carOrigin", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/carOrigin/set", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/carTarget", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/carTarget/set", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/keepAwake", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/keys", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/processRestrictions", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/processRestrictions/set", + "api_cso/cso/v1/vehicle/accessmanagement/mobiledevicekey/settings", + "api_cso/cso/v1/vehicle/accessmanagement/numberOfLearnedKeys", + "api_cso/cso/v1/vehicle/adas/cruisecontrol/acc/accStatusDisplay", + "api_cso/cso/v1/vehicle/adas/cruisecontrol/cruiseControlSystem", + "api_cso/cso/v1/vehicle/adas/cruisecontrol/cruiseControlSystemStatus", + "api_cso/cso/v1/vehicle/adas/cruisecontrol/desiredDistance", + "api_cso/cso/v1/vehicle/adas/cruisecontrol/desiredSpeed", + "api_cso/cso/v1/vehicle/adas/emergencyassist/state", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/2ndleftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/2ndrightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/2ndtargetobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/leftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/rightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/state", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontcamera/targetobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/2ndleftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/2ndrightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/2ndtargetobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/leftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/rightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/state", + "api_cso/cso/v1/vehicle/adas/objectdetection/frontfused/targetobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/fused/frontObject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/2ndleftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/2ndrightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/2ndtargetobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/leftadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/rightadjacentlaneobject", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/state", + "api_cso/cso/v1/vehicle/adas/objectdetection/rearradar/targetobject", + "api_cso/cso/v1/vehicle/antitheftsystem/isAlarming", + "api_cso/cso/v1/vehicle/antitheftsystem/isArmed", + "api_cso/cso/v1/vehicle/body/exterior/centrallocking/isLockedExternal", + "api_cso/cso/v1/vehicle/body/exterior/crashIntensity", + "api_cso/cso/v1/vehicle/body/exterior/doors/1/left", + "api_cso/cso/v1/vehicle/body/exterior/doors/1/right", + "api_cso/cso/v1/vehicle/body/exterior/doors/2/left", + "api_cso/cso/v1/vehicle/body/exterior/doors/2/right", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/front", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/frontleft1", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/frontleft2", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/frontright1", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/frontright2", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/rearleft1", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/rearleft2", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/rearright1", + "api_cso/cso/v1/vehicle/body/exterior/flap/electrical/rearright2", + "api_cso/cso/v1/vehicle/body/exterior/hood/isClosed", + "api_cso/cso/v1/vehicle/body/exterior/lights/fog/front/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/fog/rear/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/highbeam/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/lowbeam/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/parking/left/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/parking/right/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/standing/status", + "api_cso/cso/v1/vehicle/body/exterior/lights/turnIndicator", + "api_cso/cso/v1/vehicle/body/exterior/lights/warning/isPanicModeOn", + "api_cso/cso/v1/vehicle/body/exterior/lights/warning/status", + "api_cso/cso/v1/vehicle/body/exterior/trunklid/isClosed", + "api_cso/cso/v1/vehicle/body/exterior/trunklid/isLocked", + "api_cso/cso/v1/vehicle/body/exterior/windows/1/left", + "api_cso/cso/v1/vehicle/body/exterior/windows/1/right", + "api_cso/cso/v1/vehicle/body/exterior/windows/2/left", + "api_cso/cso/v1/vehicle/body/exterior/windows/2/right", + "api_cso/cso/v1/vehicle/body/exterior/wiper/fluidStatus", + "api_cso/cso/v1/vehicle/body/exterior/wiper/front/frequency/measured", + "api_cso/cso/v1/vehicle/body/exterior/wiper/front/frequency/requested", + "api_cso/cso/v1/vehicle/body/exterior/wiper/front/interval", + "api_cso/cso/v1/vehicle/body/exterior/wiper/front/isCleaning", + "api_cso/cso/v1/vehicle/body/exterior/wiper/rear/isCleaning", + "api_cso/cso/v1/vehicle/body/interior/cabinTemperature", + "api_cso/cso/v1/vehicle/body/interior/seats/1/left/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/1/right/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/2/left/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/2/middle/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/2/right/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/3/left/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/3/middle/isBeltBuckled", + "api_cso/cso/v1/vehicle/body/interior/seats/3/right/isBeltBuckled", + "api_cso/cso/v1/vehicle/car2x/v2c/breakdowncall/isActive", + "api_cso/cso/v1/vehicle/car2x/v2c/cloudconnectivity/mobilenetwork/status", + "api_cso/cso/v1/vehicle/car2x/v2c/emergencycall/state", + "api_cso/cso/v1/vehicle/chassis/brake/parkingbrake/state", + "api_cso/cso/v1/vehicle/chassis/cluster/steeringAngle", + "api_cso/cso/v1/vehicle/chassis/stabilitymanagement/abs", + "api_cso/cso/v1/vehicle/chassis/steeringAngle", + "api_cso/cso/v1/vehicle/chassis/tires/frontleft/status", + "api_cso/cso/v1/vehicle/chassis/tires/frontright/status", + "api_cso/cso/v1/vehicle/chassis/tires/rearleft/status", + "api_cso/cso/v1/vehicle/chassis/tires/rearright/status", + "api_cso/cso/v1/vehicle/childpresencedetection/status", + "api_cso/cso/v1/vehicle/childpresencedetection/tempdeactivation", + "api_cso/cso/v1/vehicle/cluster/adaptiveCruiseAssist", + "api_cso/cso/v1/vehicle/cluster/adaptiveCruiseControl", + "api_cso/cso/v1/vehicle/cluster/mfk5/bhe", + "api_cso/cso/v1/vehicle/cluster/mfk5/cal", + "api_cso/cso/v1/vehicle/cluster/mfk5/lda", + "api_cso/cso/v1/vehicle/cluster/mfk5/wla", + "api_cso/cso/v1/vehicle/cluster/tgi/brake", + "api_cso/cso/v1/vehicle/cluster/tgi/drivingData", + "api_cso/cso/v1/vehicle/cluster/tgi/engine", + "api_cso/cso/v1/vehicle/connectivity/privacy/localServiceStates", + "api_cso/cso/v1/vehicle/connectivity/privacy/modes", + "api_cso/cso/v1/vehicle/connectivity/privacy/setupGen4", + "api_cso/cso/v1/vehicle/connectivity/privacy/setupShape3", + "api_cso/cso/v1/vehicle/connectivity/privacy/setupShape3/set", + "api_cso/cso/v1/vehicle/connectivity/privacy/topicListByResource", + "api_cso/cso/v1/vehicle/diagmaster/diagassemblystatus/get", + "api_cso/cso/v1/vehicle/diagmaster/updateassemblystatus", + "api_cso/cso/v1/vehicle/diagnostics/vendorspecific/ecuHardwareVersion", + "api_cso/cso/v1/vehicle/diagnostics/vendorspecific/ecuPartNumber", + "api_cso/cso/v1/vehicle/diagnostics/vendorspecific/ecuSerialNumber", + "api_cso/cso/v1/vehicle/diagnostics/vendorspecific/ecuSoftwareVersion", + "api_cso/cso/v1/vehicle/engines/primary/type", + "api_cso/cso/v1/vehicle/engines/secondary/type", + "api_cso/cso/v1/vehicle/extendedwakingphase/clusterWakeup", + "api_cso/cso/v1/vehicle/extendedwakingphase/hvNetworkInformation", + "api_cso/cso/v1/vehicle/extendedwakingphase/keepConnectOn/set", + "api_cso/cso/v1/vehicle/factoryreset", + "api_cso/cso/v1/vehicle/friction/estimating", + "api_cso/cso/v1/vehicle/highvoltage/battery/capacity", + "api_cso/cso/v1/vehicle/highvoltage/battery/maxChargePower", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/front", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/front/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontleft1/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontleft2/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontright1/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/frontright2/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearleft1/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearleft2/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearright1/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plug/rearright2/isLocked/set", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/front", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/frontleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/frontleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/frontright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/frontright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/rearleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/rearleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/rearright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugconnectionstate/rearright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/front", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/frontleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/frontleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/frontright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/frontright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/rearleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/rearleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/rearright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/pluglockstate/rearright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/front", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/frontleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/frontleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/frontright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/frontright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/rearleft1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/rearleft2", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/rearright1", + "api_cso/cso/v1/vehicle/highvoltage/battery/plugtype/rearright2", + "api_cso/cso/v1/vehicle/highvoltage/battery/preconditioningTemperature", + "api_cso/cso/v1/vehicle/highvoltage/battery/state/range/displayed", + "api_cso/cso/v1/vehicle/highvoltage/battery/state/range/routeBased", + "api_cso/cso/v1/vehicle/highvoltage/battery/state/range/secondary/displayed", + "api_cso/cso/v1/vehicle/highvoltage/battery/state/soc/displayed", + "api_cso/cso/v1/vehicle/highvoltage/battery/state/temperature", + "api_cso/cso/v1/vehicle/highvoltage/charging/ac/maxChargingCurrent", + "api_cso/cso/v1/vehicle/highvoltage/charging/ac/maxChargingCurrent/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/activeTargetSoc", + "api_cso/cso/v1/vehicle/highvoltage/charging/backendchargingtariffs/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/backendchargingtariffs/setEmpty", + "api_cso/cso/v1/vehicle/highvoltage/charging/backendchargingtariffs/tariffPushTrigger", + "api_cso/cso/v1/vehicle/highvoltage/charging/batteryCareMode", + "api_cso/cso/v1/vehicle/highvoltage/charging/batterycaremode/bcamactivation/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/batterycaremode/bcamStatus", + "api_cso/cso/v1/vehicle/highvoltage/charging/bulkThreshold", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargepoweradaption/adaptions", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargepoweradaption/targetchargepower/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargepoweradaption/values", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingHistory", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/acceptItSystemPeRange", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/acceptItSystemPeRange/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/compatibilityMode", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/compatibilityMode/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/modeSelection", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/modeSelection/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/navTargetSoc", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/silentCharging", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/silentCharging/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/targetSoc", + "api_cso/cso/v1/vehicle/highvoltage/charging/chargingoptions/targetSoc/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/currentChargingState", + "api_cso/cso/v1/vehicle/highvoltage/charging/energy", + "api_cso/cso/v1/vehicle/highvoltage/charging/immediateactions/startStopCharging", + "api_cso/cso/v1/vehicle/highvoltage/charging/immediateactions/startStopCharging/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/maxChargePowerCurrent", + "api_cso/cso/v1/vehicle/highvoltage/charging/mode", + "api_cso/cso/v1/vehicle/highvoltage/charging/notifications", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/ac/autoUnlock", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/ac/autoUnlock/set", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/front/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/frontleft1/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/frontleft2/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/frontright1/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/frontright2/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/rearleft1/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/rearleft2/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/rearright1/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/plug/rearright2/powerSupplyState", + "api_cso/cso/v1/vehicle/highvoltage/charging/power", + "api_cso/cso/v1/vehicle/highvoltage/charging/powerCurve", + "api_cso/cso/v1/vehicle/highvoltage/charging/powerPlan", + "api_cso/cso/v1/vehicle/highvoltage/charging/profile/activeProfileId", + "api_cso/cso/v1/vehicle/highvoltage/charging/profile/create", + "api_cso/cso/v1/vehicle/highvoltage/charging/profile/delete", + "api_cso/cso/v1/vehicle/highvoltage/charging/profile/profileIdList", + "api_cso/cso/v1/vehicle/highvoltage/charging/profile/update", + "api_cso/cso/v1/vehicle/highvoltage/charging/profiles", + "api_cso/cso/v1/vehicle/highvoltage/charging/rate", + "api_cso/cso/v1/vehicle/highvoltage/charging/reason", + "api_cso/cso/v1/vehicle/highvoltage/charging/remainingtime/bulk", + "api_cso/cso/v1/vehicle/highvoltage/charging/remainingtime/target", + "api_cso/cso/v1/vehicle/highvoltage/charging/remainingtime/targetNav", + "api_cso/cso/v1/vehicle/highvoltage/charging/scenario", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/create", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/delete", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/estimatedFinishTimeDate", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/estimatedStartTimeDate", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/nextChargingTimer", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/targetReachable", + "api_cso/cso/v1/vehicle/highvoltage/charging/timer/update", + "api_cso/cso/v1/vehicle/highvoltage/charging/timers", + "api_cso/cso/v1/vehicle/highvoltage/charging/type", + "api_cso/cso/v1/vehicle/hvac/activeTimerId", + "api_cso/cso/v1/vehicle/hvac/error", + "api_cso/cso/v1/vehicle/hvac/isWindowHeatingOn", + "api_cso/cso/v1/vehicle/hvac/isWindowHeatingOn/set", + "api_cso/cso/v1/vehicle/hvac/parkclimatization/status", + "api_cso/cso/v1/vehicle/hvac/settings/climaMode", + "api_cso/cso/v1/vehicle/hvac/settings/climaMode/set", + "api_cso/cso/v1/vehicle/hvac/settings/frontleft/isEnabled", + "api_cso/cso/v1/vehicle/hvac/settings/frontleft/isEnabled/set", + "api_cso/cso/v1/vehicle/hvac/settings/frontright/isEnabled", + "api_cso/cso/v1/vehicle/hvac/settings/frontright/isEnabled/set", + "api_cso/cso/v1/vehicle/hvac/settings/isClimaOnAtUnlock", + "api_cso/cso/v1/vehicle/hvac/settings/isClimaOnAtUnlock/set", + "api_cso/cso/v1/vehicle/hvac/settings/isMirrorHeatingAllowed", + "api_cso/cso/v1/vehicle/hvac/settings/isMirrorHeatingAllowed/set", + "api_cso/cso/v1/vehicle/hvac/settings/rearleft/isEnabled", + "api_cso/cso/v1/vehicle/hvac/settings/rearleft/isEnabled/set", + "api_cso/cso/v1/vehicle/hvac/settings/rearright/isEnabled", + "api_cso/cso/v1/vehicle/hvac/settings/rearright/isEnabled/set", + "api_cso/cso/v1/vehicle/hvac/settings/targetTemperature", + "api_cso/cso/v1/vehicle/hvac/settings/targetTemperature/set", + "api_cso/cso/v1/vehicle/hvac/state", + "api_cso/cso/v1/vehicle/hvac/state/activationReason", + "api_cso/cso/v1/vehicle/hvac/state/remainingTime", + "api_cso/cso/v1/vehicle/hvac/state/requiredRunningTime", + "api_cso/cso/v1/vehicle/hvac/state/requiredRunningTime/set", + "api_cso/cso/v1/vehicle/hvac/state/set", + "api_cso/cso/v1/vehicle/hybridarchitecture/cloudonly_edgetest_v1/createGame", + "api_cso/cso/v1/vehicle/hybridarchitecture/cloudonly_edgetest_v1/joinGame", + "api_cso/cso/v1/vehicle/hybridarchitecture/cloudonly_edgetest_v1/watchGame", + "api_cso/cso/v1/vehicle/hybridarchitecture/edgetest_v1/createGame", + "api_cso/cso/v1/vehicle/hybridarchitecture/edgetest_v1/joinGame", + "api_cso/cso/v1/vehicle/hybridarchitecture/edgetest_v1/recordGame/{placeholder}", + "api_cso/cso/v1/vehicle/hybridarchitecture/edgetest_v1/watchGame", + "api_cso/cso/v1/vehicle/infotainment/settings/systemLanguage", + "api_cso/cso/v1/vehicle/infotainment/settings/user/date", + "api_cso/cso/v1/vehicle/infotainment/settings/user/time", + "api_cso/cso/v1/vehicle/infotainment/time/pltOffset", + "api_cso/cso/v1/vehicle/location/detailed/deadReckoning", + "api_cso/cso/v1/vehicle/location/detailed/deadReckoningWithoutMM", + "api_cso/cso/v1/vehicle/location/detailed/localizationType", + "api_cso/cso/v1/vehicle/location/detailed/positionsQuality", + "api_cso/cso/v1/vehicle/location/detailed/rawGnss", + "api_cso/cso/v1/vehicle/maintenance/daysToInspection", + "api_cso/cso/v1/vehicle/maintenance/daysToOilChange", + "api_cso/cso/v1/vehicle/maintenance/remainingRangeToInspection", + "api_cso/cso/v1/vehicle/maintenance/remainingRangeToOilChange", + "api_cso/cso/v1/vehicle/mfk5/bhe", + "api_cso/cso/v1/vehicle/motion/lateral/acceleration", + "api_cso/cso/v1/vehicle/motion/longitudinal/acceleration", + "api_cso/cso/v1/vehicle/motion/longitudinal/speed/displayed", + "api_cso/cso/v1/vehicle/motion/longitudinal/speed/esp", + "api_cso/cso/v1/vehicle/motion/longitudinal/speed/measured", + "api_cso/cso/v1/vehicle/motion/vertical/yawRate", + "api_cso/cso/v1/vehicle/pduid", + "api_cso/cso/v1/vehicle/pduid/{pduid}", + "api_cso/cso/v1/vehicle/pduid/0x1", + "api_cso/cso/v1/vehicle/pduid/0x14e", + "api_cso/cso/v1/vehicle/pduid/0x15b", + "api_cso/cso/v1/vehicle/pduid/0x163", + "api_cso/cso/v1/vehicle/pduid/0x165", + "api_cso/cso/v1/vehicle/pduid/0x16a", + "api_cso/cso/v1/vehicle/pduid/0x171", + "api_cso/cso/v1/vehicle/pduid/0x172", + "api_cso/cso/v1/vehicle/pduid/0x173", + "api_cso/cso/v1/vehicle/pduid/0x174", + "api_cso/cso/v1/vehicle/pduid/0x175", + "api_cso/cso/v1/vehicle/pduid/0x176", + "api_cso/cso/v1/vehicle/pduid/0x177", + "api_cso/cso/v1/vehicle/pduid/0x178", + "api_cso/cso/v1/vehicle/pduid/0x179", + "api_cso/cso/v1/vehicle/pduid/0x17a", + "api_cso/cso/v1/vehicle/pduid/0x17b", + "api_cso/cso/v1/vehicle/pduid/0x17c", + "api_cso/cso/v1/vehicle/pduid/0x17d", + "api_cso/cso/v1/vehicle/pduid/0x17e", + "api_cso/cso/v1/vehicle/pduid/0x17f", + "api_cso/cso/v1/vehicle/pduid/0x180", + "api_cso/cso/v1/vehicle/pduid/0x181", + "api_cso/cso/v1/vehicle/pduid/0x182", + "api_cso/cso/v1/vehicle/pduid/0x183", + "api_cso/cso/v1/vehicle/pduid/0x184", + "api_cso/cso/v1/vehicle/pduid/0x185", + "api_cso/cso/v1/vehicle/pduid/0x186", + "api_cso/cso/v1/vehicle/pduid/0x187", + "api_cso/cso/v1/vehicle/pduid/0x188", + "api_cso/cso/v1/vehicle/pduid/0x199", + "api_cso/cso/v1/vehicle/pduid/0x19a", + "api_cso/cso/v1/vehicle/pduid/0x19c", + "api_cso/cso/v1/vehicle/pduid/0x19d", + "api_cso/cso/v1/vehicle/pduid/0x19e", + "api_cso/cso/v1/vehicle/pduid/0x19f", + "api_cso/cso/v1/vehicle/pduid/0x1a0", + "api_cso/cso/v1/vehicle/pduid/0x1a1", + "api_cso/cso/v1/vehicle/pduid/0x1a2", + "api_cso/cso/v1/vehicle/pduid/0x1a3", + "api_cso/cso/v1/vehicle/pduid/0x1a4", + "api_cso/cso/v1/vehicle/pduid/0x1a5", + "api_cso/cso/v1/vehicle/pduid/0x1a6", + "api_cso/cso/v1/vehicle/pduid/0x1a7", + "api_cso/cso/v1/vehicle/pduid/0x1a8", + "api_cso/cso/v1/vehicle/pduid/0x1a9", + "api_cso/cso/v1/vehicle/pduid/0x1aa", + "api_cso/cso/v1/vehicle/pduid/0x1ab", + "api_cso/cso/v1/vehicle/pduid/0x1ac", + "api_cso/cso/v1/vehicle/pduid/0x1ad", + "api_cso/cso/v1/vehicle/pduid/0x1be", + "api_cso/cso/v1/vehicle/pduid/0x1bf", + "api_cso/cso/v1/vehicle/pduid/0x1c0", + "api_cso/cso/v1/vehicle/pduid/0x1c1", + "api_cso/cso/v1/vehicle/pduid/0x1c2", + "api_cso/cso/v1/vehicle/pduid/0x1c3", + "api_cso/cso/v1/vehicle/pduid/0x1c4", + "api_cso/cso/v1/vehicle/pduid/0x1c5", + "api_cso/cso/v1/vehicle/pduid/0x1c6", + "api_cso/cso/v1/vehicle/pduid/0x1c7", + "api_cso/cso/v1/vehicle/pduid/0x1ca", + "api_cso/cso/v1/vehicle/pduid/0x1cb", + "api_cso/cso/v1/vehicle/pduid/0x1cd", + "api_cso/cso/v1/vehicle/pduid/0x1ce", + "api_cso/cso/v1/vehicle/pduid/0x1e", + "api_cso/cso/v1/vehicle/pduid/0x1e7", + "api_cso/cso/v1/vehicle/pduid/0x20100c00", + "api_cso/cso/v1/vehicle/pduid/0x20670c00", + "api_cso/cso/v1/vehicle/pduid/0x20730c00", + "api_cso/cso/v1/vehicle/pduid/0x21060c00", + "api_cso/cso/v1/vehicle/pduid/0x21070c00", + "api_cso/cso/v1/vehicle/pduid/0x21080c00", + "api_cso/cso/v1/vehicle/pduid/0x238", + "api_cso/cso/v1/vehicle/pduid/0x24", + "api_cso/cso/v1/vehicle/pduid/0x25", + "api_cso/cso/v1/vehicle/pduid/0x26", + "api_cso/cso/v1/vehicle/pduid/0x27", + "api_cso/cso/v1/vehicle/pduid/0x28", + "api_cso/cso/v1/vehicle/pduid/0x29", + "api_cso/cso/v1/vehicle/pduid/0x2a", + "api_cso/cso/v1/vehicle/pduid/0x3", + "api_cso/cso/v1/vehicle/pduid/0x30005b01", + "api_cso/cso/v1/vehicle/pduid/0x38000800", + "api_cso/cso/v1/vehicle/pduid/0x38000900", + "api_cso/cso/v1/vehicle/pduid/0x38000a00", + "api_cso/cso/v1/vehicle/pduid/0x38000c00", + "api_cso/cso/v1/vehicle/pduid/0x38000d00", + "api_cso/cso/v1/vehicle/pduid/0x38001700", + "api_cso/cso/v1/vehicle/pduid/0x38001a00", + "api_cso/cso/v1/vehicle/pduid/0x38001c00", + "api_cso/cso/v1/vehicle/pduid/0x38002d01", + "api_cso/cso/v1/vehicle/pduid/0x38003300", + "api_cso/cso/v1/vehicle/pduid/0x38004200", + "api_cso/cso/v1/vehicle/pduid/0x38005500", + "api_cso/cso/v1/vehicle/pduid/0x38005900", + "api_cso/cso/v1/vehicle/pduid/0x38006a00", + "api_cso/cso/v1/vehicle/pduid/0x38006b00", + "api_cso/cso/v1/vehicle/pduid/0x3c", + "api_cso/cso/v1/vehicle/pduid/0x3f", + "api_cso/cso/v1/vehicle/pduid/0x4", + "api_cso/cso/v1/vehicle/pduid/0x40", + "api_cso/cso/v1/vehicle/pduid/0x41", + "api_cso/cso/v1/vehicle/pduid/0x42", + "api_cso/cso/v1/vehicle/pduid/0x43", + "api_cso/cso/v1/vehicle/pduid/0x44", + "api_cso/cso/v1/vehicle/pduid/0x45", + "api_cso/cso/v1/vehicle/pduid/0x46", + "api_cso/cso/v1/vehicle/pduid/0x47", + "api_cso/cso/v1/vehicle/pduid/0x48", + "api_cso/cso/v1/vehicle/pduid/0x49", + "api_cso/cso/v1/vehicle/pduid/0x4a", + "api_cso/cso/v1/vehicle/pduid/0x4b", + "api_cso/cso/v1/vehicle/pduid/0x4c", + "api_cso/cso/v1/vehicle/pduid/0x4d", + "api_cso/cso/v1/vehicle/pduid/0x4e", + "api_cso/cso/v1/vehicle/pduid/0x4f", + "api_cso/cso/v1/vehicle/pduid/0x5", + "api_cso/cso/v1/vehicle/pduid/0x50", + "api_cso/cso/v1/vehicle/pduid/0x50100c00", + "api_cso/cso/v1/vehicle/pduid/0x50670c00", + "api_cso/cso/v1/vehicle/pduid/0x506f0c00", + "api_cso/cso/v1/vehicle/pduid/0x50730c00", + "api_cso/cso/v1/vehicle/pduid/0x51", + "api_cso/cso/v1/vehicle/pduid/0x51060c00", + "api_cso/cso/v1/vehicle/pduid/0x51070c00", + "api_cso/cso/v1/vehicle/pduid/0x51080c00", + "api_cso/cso/v1/vehicle/pduid/0x52", + "api_cso/cso/v1/vehicle/pduid/0x53", + "api_cso/cso/v1/vehicle/pduid/0x54", + "api_cso/cso/v1/vehicle/pduid/0x55", + "api_cso/cso/v1/vehicle/pduid/0x6", + "api_cso/cso/v1/vehicle/pduid/0x60", + "api_cso/cso/v1/vehicle/pduid/0x64", + "api_cso/cso/v1/vehicle/pduid/0x7", + "api_cso/cso/v1/vehicle/pduid/0x8", + "api_cso/cso/v1/vehicle/pduid/0x9", + "api_cso/cso/v1/vehicle/pduid/0xa", + "api_cso/cso/v1/vehicle/pduid/0xa0", + "api_cso/cso/v1/vehicle/pduid/0xa8", + "api_cso/cso/v1/vehicle/pduid/0xa9", + "api_cso/cso/v1/vehicle/pduid/0xad", + "api_cso/cso/v1/vehicle/pduid/0xb", + "api_cso/cso/v1/vehicle/pduid/0xc", + "api_cso/cso/v1/vehicle/pduid/0xc0", + "api_cso/cso/v1/vehicle/pduid/0xc1", + "api_cso/cso/v1/vehicle/pduid/0xc2", + "api_cso/cso/v1/vehicle/pduid/0xc3", + "api_cso/cso/v1/vehicle/pduid/0xc4", + "api_cso/cso/v1/vehicle/pduid/0xc5", + "api_cso/cso/v1/vehicle/pduid/0xc6", + "api_cso/cso/v1/vehicle/pduid/0xd", + "api_cso/cso/v1/vehicle/pduid/0xf", + "api_cso/cso/v1/vehicle/pduid/buffer/{pduid}", + "api_cso/cso/v1/vehicle/powermanagement/clampinformation/isClamp15On", + "api_cso/cso/v1/vehicle/powermanagement/clampinformation/isClampSOn", + "api_cso/cso/v1/vehicle/powermanagement/shutOffLevel", + "api_cso/cso/v1/vehicle/powertrain/combustion/engine/lubricant/isBelowMinimum", + "api_cso/cso/v1/vehicle/powertrain/combustion/engine/lubricant/percent", + "api_cso/cso/v1/vehicle/powertrain/combustion/fuel/percent", + "api_cso/cso/v1/vehicle/powertrain/drivetrain/gearbox/reverseGear", + "api_cso/cso/v1/vehicle/remoterepair/assemblyStatus", + "api_cso/cso/v1/vehicle/remoterepair/cancelRequest", + "api_cso/cso/v1/vehicle/remoterepair/changeSessionType", + "api_cso/cso/v1/vehicle/remoterepair/closeSession", + "api_cso/cso/v1/vehicle/remoterepair/diagData", + "api_cso/cso/v1/vehicle/remoterepair/diagDataNotification", + "api_cso/cso/v1/vehicle/remoterepair/diagEntry", + "api_cso/cso/v1/vehicle/remoterepair/diagEventNotification", + "api_cso/cso/v1/vehicle/remoterepair/diagEvents", + "api_cso/cso/v1/vehicle/remoterepair/diagProcedureInterpreter", + "api_cso/cso/v1/vehicle/remoterepair/diagProcedureInterpreterNotification", + "api_cso/cso/v1/vehicle/remoterepair/diagRoutineNotification", + "api_cso/cso/v1/vehicle/remoterepair/diagRoutines", + "api_cso/cso/v1/vehicle/remoterepair/doRemoteRepair", + "api_cso/cso/v1/vehicle/remoterepair/getSessionStatus", + "api_cso/cso/v1/vehicle/remoterepair/openSession", + "api_cso/cso/v1/vehicle/remoterepair/progressNotification", + "api_cso/cso/v1/vehicle/remoterepair/remoteRepairNotification", + "api_cso/cso/v1/vehicle/remoterepair/resetDevice", + "api_cso/cso/v1/vehicle/remotestart/startRequest", + "api_cso/cso/v1/vehicle/remotestart/startResponse", + "api_cso/cso/v1/vehicle/remotestart/stopRequest", + "api_cso/cso/v1/vehicle/remotestart/updateStatus", + "api_cso/cso/v1/vehicle/specialfunctionlogin/backendRequest", + "api_cso/cso/v1/vehicle/specialfunctionlogin/backendResponse", + "api_cso/cso/v1/vehicle/specialfunctionlogin/startProcess", + "api_cso/cso/v1/vehicle/staticdata/steeringsystem/steeringWheelPosition", + "api_cso/cso/v1/vehicle/staticdata/vin", + "api_cso/cso/v1/vehicle/steeringWheelControls", + "api_cso/cso/v1/vehicle/swup/status", + "api_cso/cso/v1/vehicle/trailer/isPresent", + "api_cso/cso/v1/vehicle/tripstatistics/total/mileage", + "api_cso/cso/v1/vehicle/users/currentuser/ssoid", + "api_cso/cso/v1/vehicle/users/userlist", + "api_cso/server/v1/testClaim", + "api_cso/vcsystem/subscriptions", + "api_cso/vcsystem/v1/authentication/moclInfo", + "api_cso/vcsystem/v1/bootstrapping/updateServerConnectionInfo", + "api_cso/vcsystem/v1/bootstrapping/vcsConnectionInfo", + "api_cso/vcsystem/v1/claims/allowedtopiclist", + "api_cso/vcsystem/v1/claims/allowedtopiclist/", + "api_cso/vcsystem/v1/claims/allowedtopiclist/{iotserviceid}", + "api_cso/vcsystem/v1/claims/claimList", + "api_cso/vcsystem/v1/claims/claimList/set", + "api_cso/vcsystem/v1/csoTopicList", + "api_cso/vcsystem/v1/systemhealth", + "api_cso/vcsystem/v1/tgi/cloudoutput", + "api_cso/vcsystem/v1/tgi/cloudoutputtrigger", + "api_cso/vcsystem/v1/tokenmanagement/authcode/request", + "api_cso/vcsystem/v1/tokenmanagement/authcode/response", + "api_cso/vcsystem/v1/tokenmanagement/azpinfo", + "api_cso/vcsystem/version", + "baukasten", + "brand_code", + "brand_name", + "color", + "colors/1/code", + "colors/1/description", + "colors/1/type", + "colors/2/code", + "colors/2/description", + "colors/2/type", + "colors/3/code", + "colors/3/description", + "colors/3/type", + "colors/4/code", + "colors/4/description", + "colors/4/type", + "colors/5/code", + "colors/5/description", + "colors/5/type", + "containerupdate/autoedge/baseline/autoedgeapibaseline", + "containerupdate/autoedge/baseline/autoedgeswbundle", + "containerupdate/autoedge/baseline/vehicleplatform", + "containerupdate/autoedge/baseline/vehicleplatformrelease", + "containerupdate/autoedge/hash", + "containerupdate/edgecontainerflashsize", + "containerupdate/edgecontainerremainingflashsize", + "containerupdate/modules/cepcep", + "containerupdate/modules/ces", + "containerupdate/modules/cloud_connector", + "containerupdate/modules/detective", + "containerupdate/modules/diag4edge", + "containerupdate/modules/edge_twin", + "containerupdate/modules/EVServices", + "containerupdate/modules/MDKMOD", + "containerupdate/modules/odcmodule", + "containerupdate/modules/odcmodule_dev", + "containerupdate/modules/promoter_edgetest", + "containerupdate/modules/rcd", + "containerupdate/modules/remdownload", + "containerupdate/modules/rtk", + "containerupdate/modules/rtkbridge", + "containerupdate/modules/tgi", + "country", + "country_composition", + "country_composition_iso", + "dealers/1/dealer_id/brand", + "dealers/1/dealer_id/country", + "dealers/1/dealer_id/partner_number", + "dealers/1/role", + "dealers/1/whole_saler_number", + "dealers/2/dealer_id/brand", + "dealers/2/dealer_id/country", + "dealers/2/dealer_id/partner_number", + "dealers/2/role", + "dealers/2/whole_saler_number", + "delivery_date", + "device/1/device_name", + "device/1/device_type", + "device/1/diagnostic_address", + "device/2/device_name", + "device/2/device_type", + "device/2/diagnostic_address", + "devices/1/device_type", + "ecus/0001/ecu_number", + "ecus/0001/file_identifier", + "ecus/0001/file_version", + "ecus/0001/hw_reference_ecu_number", + "ecus/0001/hw_version", + "ecus/0001/logical_link", + "ecus/0001/sw_version", + "ecus/0001/zdc_version", + "ecus/0002/ecu_number", + "ecus/0002/file_identifier", + "ecus/0002/file_version", + "ecus/0002/hw_reference_ecu_number", + "ecus/0002/hw_version", + "ecus/0002/logical_link", + "ecus/0002/sw_version", + "ecus/0002/zdc_version", + "ecus/0003/ecu_number", + "ecus/0003/file_identifier", + "ecus/0003/file_version", + "ecus/0003/hw_reference_ecu_number", + "ecus/0003/hw_version", + "ecus/0003/logical_link", + "ecus/0003/sw_version", + "ecus/0003/zdc_version", + "ecus/0006/ecu_number", + "ecus/0006/file_identifier", + "ecus/0006/file_version", + "ecus/0006/hw_reference_ecu_number", + "ecus/0006/hw_version", + "ecus/0006/logical_link", + "ecus/0006/sw_version", + "ecus/0006/zdc_version", + "ecus/0009/ecu_number", + "ecus/0009/file_identifier", + "ecus/0009/file_version", + "ecus/0009/hw_reference_ecu_number", + "ecus/0009/hw_version", + "ecus/0009/logical_link", + "ecus/0009/sw_version", + "ecus/0009/zdc_version", + "ecus/000C/ecu_number", + "ecus/000C/file_identifier", + "ecus/000C/file_version", + "ecus/000C/hw_reference_ecu_number", + "ecus/000C/hw_version", + "ecus/000C/logical_link", + "ecus/000C/sw_version", + "ecus/000C/zdc_version", + "ecus/0013/ecu_number", + "ecus/0013/file_identifier", + "ecus/0013/file_version", + "ecus/0013/hw_reference_ecu_number", + "ecus/0013/hw_version", + "ecus/0013/logical_link", + "ecus/0013/sw_version", + "ecus/0013/zdc_version", + "ecus/0015/ecu_number", + "ecus/0015/file_identifier", + "ecus/0015/file_version", + "ecus/0015/hw_reference_ecu_number", + "ecus/0015/hw_version", + "ecus/0015/logical_link", + "ecus/0015/sw_version", + "ecus/0015/zdc_version", + "ecus/0016/ecu_number", + "ecus/0016/file_identifier", + "ecus/0016/file_version", + "ecus/0016/hw_reference_ecu_number", + "ecus/0016/hw_version", + "ecus/0016/logical_link", + "ecus/0016/sw_version", + "ecus/0016/zdc_version", + "ecus/0017/ecu_number", + "ecus/0017/file_identifier", + "ecus/0017/file_version", + "ecus/0017/hw_reference_ecu_number", + "ecus/0017/hw_version", + "ecus/0017/logical_link", + "ecus/0017/sw_version", + "ecus/0017/zdc_version", + "ecus/0019/ecu_number", + "ecus/0019/file_identifier", + "ecus/0019/file_version", + "ecus/0019/hw_reference_ecu_number", + "ecus/0019/hw_version", + "ecus/0019/logical_link", + "ecus/0019/sw_version", + "ecus/0019/zdc_version", + "ecus/0021/ecu_number", + "ecus/0021/file_identifier", + "ecus/0021/file_version", + "ecus/0021/hw_reference_ecu_number", + "ecus/0021/hw_version", + "ecus/0021/logical_link", + "ecus/0021/sw_version", + "ecus/0021/zdc_version", + "ecus/0022/ecu_number", + "ecus/0022/file_identifier", + "ecus/0022/file_version", + "ecus/0022/hw_reference_ecu_number", + "ecus/0022/hw_version", + "ecus/0022/logical_link", + "ecus/0022/sw_version", + "ecus/0022/zdc_version", + "ecus/0026/ecu_number", + "ecus/0026/file_identifier", + "ecus/0026/file_version", + "ecus/0026/hw_reference_ecu_number", + "ecus/0026/hw_version", + "ecus/0026/logical_link", + "ecus/0026/sw_version", + "ecus/0026/zdc_version", + "ecus/0029/ecu_number", + "ecus/0029/file_identifier", + "ecus/0029/file_version", + "ecus/0029/hw_reference_ecu_number", + "ecus/0029/hw_version", + "ecus/0029/logical_link", + "ecus/0029/sw_version", + "ecus/0029/zdc_version", + "ecus/002B/ecu_number", + "ecus/002B/file_identifier", + "ecus/002B/file_version", + "ecus/002B/hw_reference_ecu_number", + "ecus/002B/hw_version", + "ecus/002B/logical_link", + "ecus/002B/sw_version", + "ecus/002B/zdc_version", + "ecus/002C/ecu_number", + "ecus/002C/file_identifier", + "ecus/002C/file_version", + "ecus/002C/hw_reference_ecu_number", + "ecus/002C/hw_version", + "ecus/002C/logical_link", + "ecus/002C/sw_version", + "ecus/002C/zdc_version", + "ecus/0032/ecu_number", + "ecus/0032/file_identifier", + "ecus/0032/file_version", + "ecus/0032/hw_reference_ecu_number", + "ecus/0032/hw_version", + "ecus/0032/logical_link", + "ecus/0032/sw_version", + "ecus/0032/zdc_version", + "ecus/0036/ecu_number", + "ecus/0036/file_identifier", + "ecus/0036/file_version", + "ecus/0036/hw_reference_ecu_number", + "ecus/0036/hw_version", + "ecus/0036/logical_link", + "ecus/0036/sw_version", + "ecus/0036/zdc_version", + "ecus/0039/ecu_number", + "ecus/0039/file_identifier", + "ecus/0039/file_version", + "ecus/0039/hw_reference_ecu_number", + "ecus/0039/hw_version", + "ecus/0039/logical_link", + "ecus/0039/sw_version", + "ecus/0039/zdc_version", + "ecus/0042/ecu_number", + "ecus/0042/file_identifier", + "ecus/0042/file_version", + "ecus/0042/hw_reference_ecu_number", + "ecus/0042/hw_version", + "ecus/0042/logical_link", + "ecus/0042/sw_version", + "ecus/0042/zdc_version", + "ecus/0044/ecu_number", + "ecus/0044/file_identifier", + "ecus/0044/file_version", + "ecus/0044/hw_reference_ecu_number", + "ecus/0044/hw_version", + "ecus/0044/logical_link", + "ecus/0044/sw_version", + "ecus/0044/zdc_version", + "ecus/0046/ecu_number", + "ecus/0046/file_identifier", + "ecus/0046/file_version", + "ecus/0046/hw_reference_ecu_number", + "ecus/0046/hw_version", + "ecus/0046/logical_link", + "ecus/0046/sw_version", + "ecus/0046/zdc_version", + "ecus/0047/ecu_number", + "ecus/0047/file_identifier", + "ecus/0047/file_version", + "ecus/0047/hw_reference_ecu_number", + "ecus/0047/hw_version", + "ecus/0047/logical_link", + "ecus/0047/sw_version", + "ecus/0047/zdc_version", + "ecus/0048/ecu_number", + "ecus/0048/file_identifier", + "ecus/0048/file_version", + "ecus/0048/hw_reference_ecu_number", + "ecus/0048/hw_version", + "ecus/0048/logical_link", + "ecus/0048/sw_version", + "ecus/0048/zdc_version", + "ecus/0051/ecu_number", + "ecus/0051/file_identifier", + "ecus/0051/file_version", + "ecus/0051/hw_reference_ecu_number", + "ecus/0051/hw_version", + "ecus/0051/logical_link", + "ecus/0051/sw_version", + "ecus/0051/zdc_version", + "ecus/0052/ecu_number", + "ecus/0052/file_identifier", + "ecus/0052/file_version", + "ecus/0052/hw_reference_ecu_number", + "ecus/0052/hw_version", + "ecus/0052/logical_link", + "ecus/0052/sw_version", + "ecus/0052/zdc_version", + "ecus/005B/ecu_number", + "ecus/005B/file_identifier", + "ecus/005B/file_version", + "ecus/005B/hw_reference_ecu_number", + "ecus/005B/hw_version", + "ecus/005B/logical_link", + "ecus/005B/sw_version", + "ecus/005B/zdc_version", + "ecus/005F/ecu_number", + "ecus/005F/file_identifier", + "ecus/005F/file_version", + "ecus/005F/hw_reference_ecu_number", + "ecus/005F/hw_version", + "ecus/005F/logical_link", + "ecus/005F/sw_version", + "ecus/005F/zdc_version", + "ecus/0065/ecu_number", + "ecus/0065/file_identifier", + "ecus/0065/file_version", + "ecus/0065/hw_reference_ecu_number", + "ecus/0065/hw_version", + "ecus/0065/logical_link", + "ecus/0065/sw_version", + "ecus/0065/zdc_version", + "ecus/006C/ecu_number", + "ecus/006C/file_identifier", + "ecus/006C/file_version", + "ecus/006C/hw_reference_ecu_number", + "ecus/006C/hw_version", + "ecus/006C/logical_link", + "ecus/006C/sw_version", + "ecus/006C/zdc_version", + "ecus/0075/ecu_number", + "ecus/0075/file_identifier", + "ecus/0075/file_version", + "ecus/0075/hw_reference_ecu_number", + "ecus/0075/hw_version", + "ecus/0075/logical_link", + "ecus/0075/sw_version", + "ecus/0075/zdc_version", + "ecus/007E/ecu_number", + "ecus/007E/file_identifier", + "ecus/007E/file_version", + "ecus/007E/hw_reference_ecu_number", + "ecus/007E/hw_version", + "ecus/007E/logical_link", + "ecus/007E/sw_version", + "ecus/007E/zdc_version", + "ecus/0080/ecu_number", + "ecus/0080/file_identifier", + "ecus/0080/file_version", + "ecus/0080/hw_reference_ecu_number", + "ecus/0080/hw_version", + "ecus/0080/logical_link", + "ecus/0080/sw_version", + "ecus/0080/zdc_version", + "ecus/0081/ecu_number", + "ecus/0081/file_identifier", + "ecus/0081/file_version", + "ecus/0081/hw_reference_ecu_number", + "ecus/0081/hw_version", + "ecus/0081/logical_link", + "ecus/0081/sw_version", + "ecus/0081/zdc_version", + "ecus/0082/ecu_number", + "ecus/0082/file_identifier", + "ecus/0082/file_version", + "ecus/0082/hw_reference_ecu_number", + "ecus/0082/hw_version", + "ecus/0082/logical_link", + "ecus/0082/sw_version", + "ecus/0082/zdc_version", + "ecus/008B/ecu_number", + "ecus/008B/file_identifier", + "ecus/008B/file_version", + "ecus/008B/hw_reference_ecu_number", + "ecus/008B/hw_version", + "ecus/008B/logical_link", + "ecus/008B/sw_version", + "ecus/008B/zdc_version", + "ecus/008C/ecu_number", + "ecus/008C/file_identifier", + "ecus/008C/file_version", + "ecus/008C/hw_reference_ecu_number", + "ecus/008C/hw_version", + "ecus/008C/logical_link", + "ecus/008C/sw_version", + "ecus/008C/zdc_version", + "ecus/00A5/ecu_number", + "ecus/00A5/file_identifier", + "ecus/00A5/file_version", + "ecus/00A5/hw_reference_ecu_number", + "ecus/00A5/hw_version", + "ecus/00A5/logical_link", + "ecus/00A5/sw_version", + "ecus/00A5/zdc_version", + "ecus/00AE/ecu_number", + "ecus/00AE/file_identifier", + "ecus/00AE/file_version", + "ecus/00AE/hw_reference_ecu_number", + "ecus/00AE/hw_version", + "ecus/00AE/logical_link", + "ecus/00AE/sw_version", + "ecus/00AE/zdc_version", + "ecus/00BB/ecu_number", + "ecus/00BB/file_identifier", + "ecus/00BB/file_version", + "ecus/00BB/hw_reference_ecu_number", + "ecus/00BB/hw_version", + "ecus/00BB/logical_link", + "ecus/00BB/sw_version", + "ecus/00BB/zdc_version", + "ecus/00BC/ecu_number", + "ecus/00BC/file_identifier", + "ecus/00BC/file_version", + "ecus/00BC/hw_reference_ecu_number", + "ecus/00BC/hw_version", + "ecus/00BC/logical_link", + "ecus/00BC/sw_version", + "ecus/00BC/zdc_version", + "ecus/00C3/ecu_number", + "ecus/00C3/file_identifier", + "ecus/00C3/file_version", + "ecus/00C3/hw_reference_ecu_number", + "ecus/00C3/hw_version", + "ecus/00C3/logical_link", + "ecus/00C3/sw_version", + "ecus/00C3/zdc_version", + "ecus/00C4/ecu_number", + "ecus/00C4/file_identifier", + "ecus/00C4/file_version", + "ecus/00C4/hw_reference_ecu_number", + "ecus/00C4/hw_version", + "ecus/00C4/logical_link", + "ecus/00C4/sw_version", + "ecus/00C4/zdc_version", + "ecus/00C5/ecu_number", + "ecus/00C5/file_identifier", + "ecus/00C5/file_version", + "ecus/00C5/hw_reference_ecu_number", + "ecus/00C5/hw_version", + "ecus/00C5/logical_link", + "ecus/00C5/sw_version", + "ecus/00C5/zdc_version", + "ecus/00CA/ecu_number", + "ecus/00CA/file_identifier", + "ecus/00CA/file_version", + "ecus/00CA/hw_reference_ecu_number", + "ecus/00CA/hw_version", + "ecus/00CA/logical_link", + "ecus/00CA/sw_version", + "ecus/00CA/zdc_version", + "ecus/00CB/ecu_number", + "ecus/00CB/file_identifier", + "ecus/00CB/file_version", + "ecus/00CB/hw_reference_ecu_number", + "ecus/00CB/hw_version", + "ecus/00CB/logical_link", + "ecus/00CB/sw_version", + "ecus/00CB/zdc_version", + "ecus/00CC/ecu_number", + "ecus/00CC/file_identifier", + "ecus/00CC/file_version", + "ecus/00CC/hw_reference_ecu_number", + "ecus/00CC/hw_version", + "ecus/00CC/logical_link", + "ecus/00CC/sw_version", + "ecus/00CC/zdc_version", + "ecus/00CE/ecu_number", + "ecus/00CE/file_identifier", + "ecus/00CE/file_version", + "ecus/00CE/hw_reference_ecu_number", + "ecus/00CE/hw_version", + "ecus/00CE/logical_link", + "ecus/00CE/sw_version", + "ecus/00CE/zdc_version", + "ecus/00D4/ecu_number", + "ecus/00D4/file_identifier", + "ecus/00D4/file_version", + "ecus/00D4/hw_reference_ecu_number", + "ecus/00D4/hw_version", + "ecus/00D4/logical_link", + "ecus/00D4/sw_version", + "ecus/00D4/zdc_version", + "ecus/00D5/ecu_number", + "ecus/00D5/file_identifier", + "ecus/00D5/file_version", + "ecus/00D5/hw_reference_ecu_number", + "ecus/00D5/hw_version", + "ecus/00D5/logical_link", + "ecus/00D5/sw_version", + "ecus/00D5/zdc_version", + "ecus/00D6/ecu_number", + "ecus/00D6/file_identifier", + "ecus/00D6/file_version", + "ecus/00D6/hw_reference_ecu_number", + "ecus/00D6/hw_version", + "ecus/00D6/logical_link", + "ecus/00D6/sw_version", + "ecus/00D6/zdc_version", + "ecus/00D7/ecu_number", + "ecus/00D7/file_identifier", + "ecus/00D7/file_version", + "ecus/00D7/hw_reference_ecu_number", + "ecus/00D7/hw_version", + "ecus/00D7/logical_link", + "ecus/00D7/sw_version", + "ecus/00D7/zdc_version", + "ecus/00D8/ecu_number", + "ecus/00D8/file_identifier", + "ecus/00D8/file_version", + "ecus/00D8/hw_reference_ecu_number", + "ecus/00D8/hw_version", + "ecus/00D8/logical_link", + "ecus/00D8/sw_version", + "ecus/00D8/zdc_version", + "ecus/00D9/ecu_number", + "ecus/00D9/file_identifier", + "ecus/00D9/file_version", + "ecus/00D9/hw_reference_ecu_number", + "ecus/00D9/hw_version", + "ecus/00D9/logical_link", + "ecus/00D9/sw_version", + "ecus/00D9/zdc_version", + "ecus/00DE/ecu_number", + "ecus/00DE/file_identifier", + "ecus/00DE/file_version", + "ecus/00DE/hw_reference_ecu_number", + "ecus/00DE/hw_version", + "ecus/00DE/logical_link", + "ecus/00DE/sw_version", + "ecus/00DE/zdc_version", + "ecus/0601/ecu_number", + "ecus/0601/hw_reference_ecu_number", + "ecus/0601/hw_version", + "ecus/0601/logical_link", + "ecus/0601/master_diagnostic_address", + "ecus/0601/sw_version", + "ecus/0602/ecu_number", + "ecus/0602/hw_reference_ecu_number", + "ecus/0602/hw_version", + "ecus/0602/logical_link", + "ecus/0602/master_diagnostic_address", + "ecus/0602/sw_version", + "ecus/0603/ecu_number", + "ecus/0603/hw_reference_ecu_number", + "ecus/0603/hw_version", + "ecus/0603/logical_link", + "ecus/0603/master_diagnostic_address", + "ecus/0603/sw_version", + "ecus/0604/ecu_number", + "ecus/0604/hw_reference_ecu_number", + "ecus/0604/hw_version", + "ecus/0604/logical_link", + "ecus/0604/master_diagnostic_address", + "ecus/0604/sw_version", + "ecus/0611/ecu_number", + "ecus/0611/hw_reference_ecu_number", + "ecus/0611/hw_version", + "ecus/0611/logical_link", + "ecus/0611/master_diagnostic_address", + "ecus/0611/sw_version", + "ecus/0616/ecu_number", + "ecus/0616/hw_reference_ecu_number", + "ecus/0616/hw_version", + "ecus/0616/logical_link", + "ecus/0616/master_diagnostic_address", + "ecus/0616/sw_version", + "ecus/0618/ecu_number", + "ecus/0618/hw_reference_ecu_number", + "ecus/0618/hw_version", + "ecus/0618/logical_link", + "ecus/0618/master_diagnostic_address", + "ecus/0618/sw_version", + "ecus/0619/ecu_number", + "ecus/0619/hw_reference_ecu_number", + "ecus/0619/hw_version", + "ecus/0619/logical_link", + "ecus/0619/master_diagnostic_address", + "ecus/0619/sw_version", + "ecus/061B/ecu_number", + "ecus/061B/hw_reference_ecu_number", + "ecus/061B/hw_version", + "ecus/061B/logical_link", + "ecus/061B/master_diagnostic_address", + "ecus/061B/sw_version", + "ecus/061E/ecu_number", + "ecus/061E/hw_reference_ecu_number", + "ecus/061E/hw_version", + "ecus/061E/logical_link", + "ecus/061E/master_diagnostic_address", + "ecus/061E/sw_version", + "ecus/061F/ecu_number", + "ecus/061F/hw_reference_ecu_number", + "ecus/061F/hw_version", + "ecus/061F/logical_link", + "ecus/061F/master_diagnostic_address", + "ecus/061F/sw_version", + "ecus/0624/ecu_number", + "ecus/0624/hw_reference_ecu_number", + "ecus/0624/hw_version", + "ecus/0624/logical_link", + "ecus/0624/master_diagnostic_address", + "ecus/0624/sw_version", + "ecus/0625/ecu_number", + "ecus/0625/hw_reference_ecu_number", + "ecus/0625/hw_version", + "ecus/0625/logical_link", + "ecus/0625/master_diagnostic_address", + "ecus/0625/sw_version", + "ecus/062A/ecu_number", + "ecus/062A/hw_reference_ecu_number", + "ecus/062A/hw_version", + "ecus/062A/logical_link", + "ecus/062A/master_diagnostic_address", + "ecus/062A/sw_version", + "ecus/062B/ecu_number", + "ecus/062B/hw_reference_ecu_number", + "ecus/062B/hw_version", + "ecus/062B/logical_link", + "ecus/062B/master_diagnostic_address", + "ecus/062B/sw_version", + "ecus/0630/ecu_number", + "ecus/0630/hw_reference_ecu_number", + "ecus/0630/hw_version", + "ecus/0630/logical_link", + "ecus/0630/master_diagnostic_address", + "ecus/0630/sw_version", + "ecus/0637/ecu_number", + "ecus/0637/hw_reference_ecu_number", + "ecus/0637/hw_version", + "ecus/0637/logical_link", + "ecus/0637/master_diagnostic_address", + "ecus/0637/sw_version", + "ecus/0648/ecu_number", + "ecus/0648/hw_reference_ecu_number", + "ecus/0648/hw_version", + "ecus/0648/logical_link", + "ecus/0648/master_diagnostic_address", + "ecus/0648/sw_version", + "ecus/0649/ecu_number", + "ecus/0649/hw_reference_ecu_number", + "ecus/0649/hw_version", + "ecus/0649/logical_link", + "ecus/0649/master_diagnostic_address", + "ecus/0649/sw_version", + "ecus/064E/ecu_number", + "ecus/064E/hw_reference_ecu_number", + "ecus/064E/hw_version", + "ecus/064E/logical_link", + "ecus/064E/master_diagnostic_address", + "ecus/064E/sw_version", + "ecus/0650/ecu_number", + "ecus/0650/hw_reference_ecu_number", + "ecus/0650/hw_version", + "ecus/0650/logical_link", + "ecus/0650/master_diagnostic_address", + "ecus/0650/sw_version", + "ecus/0651/ecu_number", + "ecus/0651/hw_reference_ecu_number", + "ecus/0651/hw_version", + "ecus/0651/logical_link", + "ecus/0651/master_diagnostic_address", + "ecus/0651/sw_version", + "ecus/065D/ecu_number", + "ecus/065D/hw_reference_ecu_number", + "ecus/065D/hw_version", + "ecus/065D/logical_link", + "ecus/065D/master_diagnostic_address", + "ecus/065D/sw_version", + "ecus/0669/ecu_number", + "ecus/0669/hw_reference_ecu_number", + "ecus/0669/hw_version", + "ecus/0669/logical_link", + "ecus/0669/master_diagnostic_address", + "ecus/0669/sw_version", + "ecus/066A/ecu_number", + "ecus/066A/hw_reference_ecu_number", + "ecus/066A/hw_version", + "ecus/066A/logical_link", + "ecus/066A/master_diagnostic_address", + "ecus/066A/sw_version", + "ecus/0672/ecu_number", + "ecus/0672/hw_reference_ecu_number", + "ecus/0672/hw_version", + "ecus/0672/logical_link", + "ecus/0672/master_diagnostic_address", + "ecus/0672/sw_version", + "ecus/068E/ecu_number", + "ecus/068E/hw_reference_ecu_number", + "ecus/068E/hw_version", + "ecus/068E/logical_link", + "ecus/068E/master_diagnostic_address", + "ecus/068E/sw_version", + "ecus/0692/ecu_number", + "ecus/0692/hw_reference_ecu_number", + "ecus/0692/hw_version", + "ecus/0692/logical_link", + "ecus/0692/master_diagnostic_address", + "ecus/0692/sw_version", + "ecus/0693/ecu_number", + "ecus/0693/hw_reference_ecu_number", + "ecus/0693/hw_version", + "ecus/0693/logical_link", + "ecus/0693/master_diagnostic_address", + "ecus/0693/sw_version", + "ecus/06AE/ecu_number", + "ecus/06AE/hw_reference_ecu_number", + "ecus/06AE/hw_version", + "ecus/06AE/logical_link", + "ecus/06AE/master_diagnostic_address", + "ecus/06AE/sw_version", + "ecus/06AF/ecu_number", + "ecus/06AF/hw_reference_ecu_number", + "ecus/06AF/hw_version", + "ecus/06AF/logical_link", + "ecus/06AF/master_diagnostic_address", + "ecus/06AF/sw_version", + "ecus/06B9/ecu_number", + "ecus/06B9/hw_reference_ecu_number", + "ecus/06B9/hw_version", + "ecus/06B9/logical_link", + "ecus/06B9/master_diagnostic_address", + "ecus/06B9/sw_version", + "ecus/06BA/ecu_number", + "ecus/06BA/hw_reference_ecu_number", + "ecus/06BA/hw_version", + "ecus/06BA/logical_link", + "ecus/06BA/master_diagnostic_address", + "ecus/06BA/sw_version", + "ecus/06BD/ecu_number", + "ecus/06BD/hw_reference_ecu_number", + "ecus/06BD/hw_version", + "ecus/06BD/logical_link", + "ecus/06BD/master_diagnostic_address", + "ecus/06BD/sw_version", + "ecus/06BE/ecu_number", + "ecus/06BE/hw_reference_ecu_number", + "ecus/06BE/hw_version", + "ecus/06BE/logical_link", + "ecus/06BE/master_diagnostic_address", + "ecus/06BE/sw_version", + "ecus/06C1/ecu_number", + "ecus/06C1/hw_reference_ecu_number", + "ecus/06C1/hw_version", + "ecus/06C1/logical_link", + "ecus/06C1/master_diagnostic_address", + "ecus/06C1/sw_version", + "ecus/06C3/ecu_number", + "ecus/06C3/hw_reference_ecu_number", + "ecus/06C3/hw_version", + "ecus/06C3/logical_link", + "ecus/06C3/master_diagnostic_address", + "ecus/06C3/sw_version", + "ecus/06C5/ecu_number", + "ecus/06C5/hw_reference_ecu_number", + "ecus/06C5/hw_version", + "ecus/06C5/logical_link", + "ecus/06C5/master_diagnostic_address", + "ecus/06C5/sw_version", + "ecus/06C7/ecu_number", + "ecus/06C7/hw_reference_ecu_number", + "ecus/06C7/hw_version", + "ecus/06C7/logical_link", + "ecus/06C7/master_diagnostic_address", + "ecus/06C7/sw_version", + "ecus/06EC/ecu_number", + "ecus/06EC/hw_reference_ecu_number", + "ecus/06EC/hw_version", + "ecus/06EC/logical_link", + "ecus/06EC/master_diagnostic_address", + "ecus/06EC/sw_version", + "ecus/06ED/ecu_number", + "ecus/06ED/hw_reference_ecu_number", + "ecus/06ED/hw_version", + "ecus/06ED/logical_link", + "ecus/06ED/master_diagnostic_address", + "ecus/06ED/sw_version", + "ecus/06F8/ecu_number", + "ecus/06F8/hw_reference_ecu_number", + "ecus/06F8/hw_version", + "ecus/06F8/logical_link", + "ecus/06F8/master_diagnostic_address", + "ecus/06F8/sw_version", + "ecus/06F9/ecu_number", + "ecus/06F9/hw_reference_ecu_number", + "ecus/06F9/hw_version", + "ecus/06F9/logical_link", + "ecus/06F9/master_diagnostic_address", + "ecus/06F9/sw_version", + "ecus/0701/ecu_number", + "ecus/0701/hw_reference_ecu_number", + "ecus/0701/hw_version", + "ecus/0701/logical_link", + "ecus/0701/master_diagnostic_address", + "ecus/0701/sw_version", + "ecus/0702/ecu_number", + "ecus/0702/hw_reference_ecu_number", + "ecus/0702/hw_version", + "ecus/0702/logical_link", + "ecus/0702/master_diagnostic_address", + "ecus/0702/sw_version", + "ecus/0703/ecu_number", + "ecus/0703/hw_reference_ecu_number", + "ecus/0703/hw_version", + "ecus/0703/logical_link", + "ecus/0703/master_diagnostic_address", + "ecus/0703/sw_version", + "ecus/0704/ecu_number", + "ecus/0704/hw_reference_ecu_number", + "ecus/0704/hw_version", + "ecus/0704/logical_link", + "ecus/0704/master_diagnostic_address", + "ecus/0704/sw_version", + "ecus/0705/ecu_number", + "ecus/0705/hw_reference_ecu_number", + "ecus/0705/hw_version", + "ecus/0705/logical_link", + "ecus/0705/master_diagnostic_address", + "ecus/0705/sw_version", + "ecus/0707/ecu_number", + "ecus/0707/hw_reference_ecu_number", + "ecus/0707/hw_version", + "ecus/0707/logical_link", + "ecus/0707/master_diagnostic_address", + "ecus/0707/sw_version", + "ecus/0709/ecu_number", + "ecus/0709/hw_reference_ecu_number", + "ecus/0709/hw_version", + "ecus/0709/logical_link", + "ecus/0709/master_diagnostic_address", + "ecus/0709/sw_version", + "ecus/070A/ecu_number", + "ecus/070A/hw_reference_ecu_number", + "ecus/070A/hw_version", + "ecus/070A/logical_link", + "ecus/070A/master_diagnostic_address", + "ecus/070A/sw_version", + "ecus/070E/ecu_number", + "ecus/070E/hw_reference_ecu_number", + "ecus/070E/hw_version", + "ecus/070E/logical_link", + "ecus/070E/master_diagnostic_address", + "ecus/070E/sw_version", + "ecus/070F/ecu_number", + "ecus/070F/hw_reference_ecu_number", + "ecus/070F/hw_version", + "ecus/070F/logical_link", + "ecus/070F/master_diagnostic_address", + "ecus/070F/sw_version", + "ecus/0710/ecu_number", + "ecus/0710/hw_reference_ecu_number", + "ecus/0710/hw_version", + "ecus/0710/logical_link", + "ecus/0710/master_diagnostic_address", + "ecus/0710/sw_version", + "ecus/0712/ecu_number", + "ecus/0712/hw_reference_ecu_number", + "ecus/0712/hw_version", + "ecus/0712/logical_link", + "ecus/0712/master_diagnostic_address", + "ecus/0712/sw_version", + "ecus/0713/ecu_number", + "ecus/0713/hw_reference_ecu_number", + "ecus/0713/hw_version", + "ecus/0713/logical_link", + "ecus/0713/master_diagnostic_address", + "ecus/0713/sw_version", + "ecus/0716/ecu_number", + "ecus/0716/hw_reference_ecu_number", + "ecus/0716/hw_version", + "ecus/0716/logical_link", + "ecus/0716/master_diagnostic_address", + "ecus/0716/sw_version", + "ecus/0717/ecu_number", + "ecus/0717/hw_reference_ecu_number", + "ecus/0717/hw_version", + "ecus/0717/logical_link", + "ecus/0717/master_diagnostic_address", + "ecus/0717/sw_version", + "ecus/072A/ecu_number", + "ecus/072A/hw_reference_ecu_number", + "ecus/072A/hw_version", + "ecus/072A/logical_link", + "ecus/072A/master_diagnostic_address", + "ecus/072A/sw_version", + "ecus/072B/ecu_number", + "ecus/072B/hw_reference_ecu_number", + "ecus/072B/hw_version", + "ecus/072B/logical_link", + "ecus/072B/master_diagnostic_address", + "ecus/072B/sw_version", + "ecus/072C/ecu_number", + "ecus/072C/hw_reference_ecu_number", + "ecus/072C/hw_version", + "ecus/072C/logical_link", + "ecus/072C/master_diagnostic_address", + "ecus/072C/sw_version", + "ecus/0737/ecu_number", + "ecus/0737/hw_reference_ecu_number", + "ecus/0737/hw_version", + "ecus/0737/logical_link", + "ecus/0737/master_diagnostic_address", + "ecus/0737/sw_version", + "ecus/073E/ecu_number", + "ecus/073E/hw_reference_ecu_number", + "ecus/073E/hw_version", + "ecus/073E/logical_link", + "ecus/073E/master_diagnostic_address", + "ecus/073E/sw_version", + "ecus/0743/ecu_number", + "ecus/0743/hw_reference_ecu_number", + "ecus/0743/hw_version", + "ecus/0743/logical_link", + "ecus/0743/master_diagnostic_address", + "ecus/0743/sw_version", + "ecus/0745/ecu_number", + "ecus/0745/hw_reference_ecu_number", + "ecus/0745/hw_version", + "ecus/0745/logical_link", + "ecus/0745/master_diagnostic_address", + "ecus/0745/sw_version", + "ecus/0746/ecu_number", + "ecus/0746/hw_reference_ecu_number", + "ecus/0746/hw_version", + "ecus/0746/logical_link", + "ecus/0746/master_diagnostic_address", + "ecus/0746/sw_version", + "ecus/0747/ecu_number", + "ecus/0747/hw_reference_ecu_number", + "ecus/0747/hw_version", + "ecus/0747/logical_link", + "ecus/0747/master_diagnostic_address", + "ecus/0747/sw_version", + "ecus/074A/ecu_number", + "ecus/074A/hw_reference_ecu_number", + "ecus/074A/hw_version", + "ecus/074A/logical_link", + "ecus/074A/master_diagnostic_address", + "ecus/074A/sw_version", + "ecus/0757/ecu_number", + "ecus/0757/hw_reference_ecu_number", + "ecus/0757/hw_version", + "ecus/0757/logical_link", + "ecus/0757/master_diagnostic_address", + "ecus/0757/sw_version", + "ecus/0758/ecu_number", + "ecus/0758/hw_reference_ecu_number", + "ecus/0758/hw_version", + "ecus/0758/logical_link", + "ecus/0758/master_diagnostic_address", + "ecus/0758/sw_version", + "ecus/075B/ecu_number", + "ecus/075B/hw_reference_ecu_number", + "ecus/075B/hw_version", + "ecus/075B/logical_link", + "ecus/075B/master_diagnostic_address", + "ecus/075B/sw_version", + "ecus/075E/ecu_number", + "ecus/075E/hw_reference_ecu_number", + "ecus/075E/hw_version", + "ecus/075E/logical_link", + "ecus/075E/master_diagnostic_address", + "ecus/075E/sw_version", + "ecus/075F/ecu_number", + "ecus/075F/hw_reference_ecu_number", + "ecus/075F/hw_version", + "ecus/075F/logical_link", + "ecus/075F/master_diagnostic_address", + "ecus/075F/sw_version", + "ecus/0765/ecu_number", + "ecus/0765/hw_reference_ecu_number", + "ecus/0765/hw_version", + "ecus/0765/logical_link", + "ecus/0765/master_diagnostic_address", + "ecus/0765/sw_version", + "ecus/0766/ecu_number", + "ecus/0766/hw_reference_ecu_number", + "ecus/0766/hw_version", + "ecus/0766/logical_link", + "ecus/0766/master_diagnostic_address", + "ecus/0766/sw_version", + "ecus/076A/ecu_number", + "ecus/076A/hw_reference_ecu_number", + "ecus/076A/hw_version", + "ecus/076A/logical_link", + "ecus/076A/master_diagnostic_address", + "ecus/076A/sw_version", + "ecus/076B/ecu_number", + "ecus/076B/hw_reference_ecu_number", + "ecus/076B/hw_version", + "ecus/076B/logical_link", + "ecus/076B/master_diagnostic_address", + "ecus/076B/sw_version", + "ecus/076C/ecu_number", + "ecus/076C/hw_reference_ecu_number", + "ecus/076C/hw_version", + "ecus/076C/logical_link", + "ecus/076C/master_diagnostic_address", + "ecus/076C/sw_version", + "ecus/076D/ecu_number", + "ecus/076D/hw_reference_ecu_number", + "ecus/076D/hw_version", + "ecus/076D/logical_link", + "ecus/076D/master_diagnostic_address", + "ecus/076D/sw_version", + "ecus/0777/ecu_number", + "ecus/0777/hw_reference_ecu_number", + "ecus/0777/hw_version", + "ecus/0777/logical_link", + "ecus/0777/master_diagnostic_address", + "ecus/0777/sw_version", + "ecus/0778/ecu_number", + "ecus/0778/hw_reference_ecu_number", + "ecus/0778/hw_version", + "ecus/0778/logical_link", + "ecus/0778/master_diagnostic_address", + "ecus/0778/sw_version", + "ecus/0779/ecu_number", + "ecus/0779/hw_reference_ecu_number", + "ecus/0779/hw_version", + "ecus/0779/logical_link", + "ecus/0779/master_diagnostic_address", + "ecus/0779/sw_version", + "ecus/077A/ecu_number", + "ecus/077A/hw_reference_ecu_number", + "ecus/077A/hw_version", + "ecus/077A/logical_link", + "ecus/077A/master_diagnostic_address", + "ecus/077A/sw_version", + "ecus/0783/ecu_number", + "ecus/0783/hw_reference_ecu_number", + "ecus/0783/hw_version", + "ecus/0783/logical_link", + "ecus/0783/master_diagnostic_address", + "ecus/0783/sw_version", + "ecus/0784/ecu_number", + "ecus/0784/hw_reference_ecu_number", + "ecus/0784/hw_version", + "ecus/0784/logical_link", + "ecus/0784/master_diagnostic_address", + "ecus/0784/sw_version", + "ecus/0785/ecu_number", + "ecus/0785/hw_reference_ecu_number", + "ecus/0785/hw_version", + "ecus/0785/logical_link", + "ecus/0785/master_diagnostic_address", + "ecus/0785/sw_version", + "ecus/0786/ecu_number", + "ecus/0786/hw_reference_ecu_number", + "ecus/0786/hw_version", + "ecus/0786/logical_link", + "ecus/0786/master_diagnostic_address", + "ecus/0786/sw_version", + "ecus/0787/ecu_number", + "ecus/0787/hw_reference_ecu_number", + "ecus/0787/hw_version", + "ecus/0787/logical_link", + "ecus/0787/master_diagnostic_address", + "ecus/0787/sw_version", + "ecus/0789/ecu_number", + "ecus/0789/hw_reference_ecu_number", + "ecus/0789/hw_version", + "ecus/0789/logical_link", + "ecus/0789/master_diagnostic_address", + "ecus/0789/sw_version", + "ecus/078A/ecu_number", + "ecus/078A/hw_reference_ecu_number", + "ecus/078A/hw_version", + "ecus/078A/logical_link", + "ecus/078A/master_diagnostic_address", + "ecus/078A/sw_version", + "ecus/07AB/ecu_number", + "ecus/07AB/hw_reference_ecu_number", + "ecus/07AB/hw_version", + "ecus/07AB/logical_link", + "ecus/07AB/master_diagnostic_address", + "ecus/07AB/sw_version", + "ecus/07B1/ecu_number", + "ecus/07B1/hw_reference_ecu_number", + "ecus/07B1/hw_version", + "ecus/07B1/logical_link", + "ecus/07B1/master_diagnostic_address", + "ecus/07B1/sw_version", + "ecus/07B2/ecu_number", + "ecus/07B2/hw_reference_ecu_number", + "ecus/07B2/hw_version", + "ecus/07B2/logical_link", + "ecus/07B2/master_diagnostic_address", + "ecus/07B2/sw_version", + "ecus/07B3/ecu_number", + "ecus/07B3/hw_reference_ecu_number", + "ecus/07B3/hw_version", + "ecus/07B3/logical_link", + "ecus/07B3/master_diagnostic_address", + "ecus/07B3/sw_version", + "ecus/07B4/ecu_number", + "ecus/07B4/hw_reference_ecu_number", + "ecus/07B4/hw_version", + "ecus/07B4/logical_link", + "ecus/07B4/master_diagnostic_address", + "ecus/07B4/sw_version", + "ecus/07C3/ecu_number", + "ecus/07C3/hw_reference_ecu_number", + "ecus/07C3/hw_version", + "ecus/07C3/logical_link", + "ecus/07C3/master_diagnostic_address", + "ecus/07C3/sw_version", + "ecus/07C4/ecu_number", + "ecus/07C4/hw_reference_ecu_number", + "ecus/07C4/hw_version", + "ecus/07C4/logical_link", + "ecus/07C4/master_diagnostic_address", + "ecus/07C4/sw_version", + "ecus/07C5/ecu_number", + "ecus/07C5/hw_reference_ecu_number", + "ecus/07C5/hw_version", + "ecus/07C5/logical_link", + "ecus/07C5/master_diagnostic_address", + "ecus/07C5/sw_version", + "ecus/07C6/ecu_number", + "ecus/07C6/hw_reference_ecu_number", + "ecus/07C6/hw_version", + "ecus/07C6/logical_link", + "ecus/07C6/master_diagnostic_address", + "ecus/07C6/sw_version", + "ecus/07C9/ecu_number", + "ecus/07C9/hw_reference_ecu_number", + "ecus/07C9/hw_version", + "ecus/07C9/logical_link", + "ecus/07C9/master_diagnostic_address", + "ecus/07C9/sw_version", + "ecus/07CC/ecu_number", + "ecus/07CC/hw_reference_ecu_number", + "ecus/07CC/hw_version", + "ecus/07CC/logical_link", + "ecus/07CC/master_diagnostic_address", + "ecus/07CC/sw_version", + "ecus/07CE/ecu_number", + "ecus/07CE/hw_reference_ecu_number", + "ecus/07CE/hw_version", + "ecus/07CE/logical_link", + "ecus/07CE/master_diagnostic_address", + "ecus/07CE/sw_version", + "ecus/07D0/ecu_number", + "ecus/07D0/hw_reference_ecu_number", + "ecus/07D0/hw_version", + "ecus/07D0/logical_link", + "ecus/07D0/master_diagnostic_address", + "ecus/07D0/sw_version", + "ecus/07D4/ecu_number", + "ecus/07D4/hw_reference_ecu_number", + "ecus/07D4/hw_version", + "ecus/07D4/logical_link", + "ecus/07D4/master_diagnostic_address", + "ecus/07D4/sw_version", + "ecus/07D6/ecu_number", + "ecus/07D6/hw_reference_ecu_number", + "ecus/07D6/hw_version", + "ecus/07D6/logical_link", + "ecus/07D6/master_diagnostic_address", + "ecus/07D6/sw_version", + "ecus/07D8/ecu_number", + "ecus/07D8/hw_reference_ecu_number", + "ecus/07D8/hw_version", + "ecus/07D8/logical_link", + "ecus/07D8/master_diagnostic_address", + "ecus/07D8/sw_version", + "ecus/07D9/ecu_number", + "ecus/07D9/hw_reference_ecu_number", + "ecus/07D9/hw_version", + "ecus/07D9/logical_link", + "ecus/07D9/master_diagnostic_address", + "ecus/07D9/sw_version", + "ecus/07DE/ecu_number", + "ecus/07DE/hw_reference_ecu_number", + "ecus/07DE/hw_version", + "ecus/07DE/logical_link", + "ecus/07DE/master_diagnostic_address", + "ecus/07DE/sw_version", + "ecus/07DF/ecu_number", + "ecus/07DF/hw_reference_ecu_number", + "ecus/07DF/hw_version", + "ecus/07DF/logical_link", + "ecus/07DF/master_diagnostic_address", + "ecus/07DF/sw_version", + "ecus/07E2/ecu_number", + "ecus/07E2/hw_reference_ecu_number", + "ecus/07E2/hw_version", + "ecus/07E2/logical_link", + "ecus/07E2/master_diagnostic_address", + "ecus/07E2/sw_version", + "ecus/07E5/ecu_number", + "ecus/07E5/hw_reference_ecu_number", + "ecus/07E5/hw_version", + "ecus/07E5/logical_link", + "ecus/07E5/master_diagnostic_address", + "ecus/07E5/sw_version", + "ecus/07E6/ecu_number", + "ecus/07E6/hw_reference_ecu_number", + "ecus/07E6/hw_version", + "ecus/07E6/logical_link", + "ecus/07E6/master_diagnostic_address", + "ecus/07E6/sw_version", + "ecus/07E7/ecu_number", + "ecus/07E7/hw_reference_ecu_number", + "ecus/07E7/hw_version", + "ecus/07E7/logical_link", + "ecus/07E7/master_diagnostic_address", + "ecus/07E7/sw_version", + "ecus/07EE/ecu_number", + "ecus/07EE/hw_reference_ecu_number", + "ecus/07EE/hw_version", + "ecus/07EE/logical_link", + "ecus/07EE/master_diagnostic_address", + "ecus/07EE/sw_version", + "ecus/07EF/ecu_number", + "ecus/07EF/hw_reference_ecu_number", + "ecus/07EF/hw_version", + "ecus/07EF/logical_link", + "ecus/07EF/master_diagnostic_address", + "ecus/07EF/sw_version", + "ecus/100A/ecu_number", + "ecus/100A/file_identifier", + "ecus/100A/file_version", + "ecus/100A/hw_reference_ecu_number", + "ecus/100A/hw_version", + "ecus/100A/logical_link", + "ecus/100A/sw_version", + "ecus/100A/zdc_version", + "ecus/100C/ecu_number", + "ecus/100C/file_identifier", + "ecus/100C/file_version", + "ecus/100C/hw_reference_ecu_number", + "ecus/100C/hw_version", + "ecus/100C/logical_link", + "ecus/100C/sw_version", + "ecus/100C/zdc_version", + "ecus/100E/ecu_number", + "ecus/100E/file_identifier", + "ecus/100E/file_version", + "ecus/100E/hw_reference_ecu_number", + "ecus/100E/hw_version", + "ecus/100E/logical_link", + "ecus/100E/sw_version", + "ecus/100E/zdc_version", + "ecus/1010/ecu_number", + "ecus/1010/file_identifier", + "ecus/1010/file_version", + "ecus/1010/hw_reference_ecu_number", + "ecus/1010/hw_version", + "ecus/1010/logical_link", + "ecus/1010/sw_version", + "ecus/1010/zdc_version", + "ecus/1012/ecu_number", + "ecus/1012/file_identifier", + "ecus/1012/file_version", + "ecus/1012/hw_reference_ecu_number", + "ecus/1012/hw_version", + "ecus/1012/logical_link", + "ecus/1012/sw_version", + "ecus/1012/zdc_version", + "ecus/1013/ecu_number", + "ecus/1013/file_identifier", + "ecus/1013/file_version", + "ecus/1013/hw_reference_ecu_number", + "ecus/1013/hw_version", + "ecus/1013/logical_link", + "ecus/1013/sw_version", + "ecus/1013/zdc_version", + "ecus/1015/ecu_number", + "ecus/1015/file_identifier", + "ecus/1015/file_version", + "ecus/1015/hw_reference_ecu_number", + "ecus/1015/hw_version", + "ecus/1015/logical_link", + "ecus/1015/sw_version", + "ecus/1015/zdc_version", + "ecus/101B/ecu_number", + "ecus/101B/file_identifier", + "ecus/101B/file_version", + "ecus/101B/hw_reference_ecu_number", + "ecus/101B/hw_version", + "ecus/101B/logical_link", + "ecus/101B/sw_version", + "ecus/101B/zdc_version", + "ecus/1023/ecu_number", + "ecus/1023/file_identifier", + "ecus/1023/file_version", + "ecus/1023/hw_reference_ecu_number", + "ecus/1023/hw_version", + "ecus/1023/logical_link", + "ecus/1023/sw_version", + "ecus/1023/zdc_version", + "ecus/1031/ecu_number", + "ecus/1031/file_identifier", + "ecus/1031/file_version", + "ecus/1031/hw_reference_ecu_number", + "ecus/1031/hw_version", + "ecus/1031/logical_link", + "ecus/1031/sw_version", + "ecus/1031/zdc_version", + "ecus/1032/ecu_number", + "ecus/1032/file_identifier", + "ecus/1032/file_version", + "ecus/1032/hw_reference_ecu_number", + "ecus/1032/hw_version", + "ecus/1032/logical_link", + "ecus/1032/sw_version", + "ecus/1032/zdc_version", + "ecus/103B/ecu_number", + "ecus/103B/file_identifier", + "ecus/103B/file_version", + "ecus/103B/hw_reference_ecu_number", + "ecus/103B/hw_version", + "ecus/103B/logical_link", + "ecus/103B/sw_version", + "ecus/103B/zdc_version", + "ecus/103E/ecu_number", + "ecus/103E/file_identifier", + "ecus/103E/file_version", + "ecus/103E/hw_reference_ecu_number", + "ecus/103E/hw_version", + "ecus/103E/logical_link", + "ecus/103E/sw_version", + "ecus/103E/zdc_version", + "ecus/103F/ecu_number", + "ecus/103F/file_identifier", + "ecus/103F/file_version", + "ecus/103F/hw_reference_ecu_number", + "ecus/103F/hw_version", + "ecus/103F/logical_link", + "ecus/103F/sw_version", + "ecus/103F/zdc_version", + "ecus/1044/ecu_number", + "ecus/1044/file_identifier", + "ecus/1044/file_version", + "ecus/1044/hw_reference_ecu_number", + "ecus/1044/hw_version", + "ecus/1044/logical_link", + "ecus/1044/sw_version", + "ecus/1044/zdc_version", + "ecus/1046/ecu_number", + "ecus/1046/file_identifier", + "ecus/1046/file_version", + "ecus/1046/hw_reference_ecu_number", + "ecus/1046/hw_version", + "ecus/1046/logical_link", + "ecus/1046/sw_version", + "ecus/1046/zdc_version", + "ecus/1047/ecu_number", + "ecus/1047/file_identifier", + "ecus/1047/file_version", + "ecus/1047/hw_reference_ecu_number", + "ecus/1047/hw_version", + "ecus/1047/logical_link", + "ecus/1047/sw_version", + "ecus/1047/zdc_version", + "ecus/104A/ecu_number", + "ecus/104A/file_identifier", + "ecus/104A/file_version", + "ecus/104A/hw_reference_ecu_number", + "ecus/104A/hw_version", + "ecus/104A/logical_link", + "ecus/104A/sw_version", + "ecus/104A/zdc_version", + "ecus/104B/ecu_number", + "ecus/104B/file_identifier", + "ecus/104B/file_version", + "ecus/104B/hw_reference_ecu_number", + "ecus/104B/hw_version", + "ecus/104B/logical_link", + "ecus/104B/sw_version", + "ecus/104B/zdc_version", + "ecus/104C/ecu_number", + "ecus/104C/file_identifier", + "ecus/104C/file_version", + "ecus/104C/hw_reference_ecu_number", + "ecus/104C/hw_version", + "ecus/104C/logical_link", + "ecus/104C/sw_version", + "ecus/104C/zdc_version", + "ecus/104D/ecu_number", + "ecus/104D/file_identifier", + "ecus/104D/file_version", + "ecus/104D/hw_reference_ecu_number", + "ecus/104D/hw_version", + "ecus/104D/logical_link", + "ecus/104D/sw_version", + "ecus/104D/zdc_version", + "ecus/104E/ecu_number", + "ecus/104E/file_identifier", + "ecus/104E/file_version", + "ecus/104E/hw_reference_ecu_number", + "ecus/104E/hw_version", + "ecus/104E/logical_link", + "ecus/104E/sw_version", + "ecus/104E/zdc_version", + "ecus/104F/ecu_number", + "ecus/104F/file_identifier", + "ecus/104F/file_version", + "ecus/104F/hw_reference_ecu_number", + "ecus/104F/hw_version", + "ecus/104F/logical_link", + "ecus/104F/sw_version", + "ecus/104F/zdc_version", + "ecus/1057/ecu_number", + "ecus/1057/file_identifier", + "ecus/1057/file_version", + "ecus/1057/hw_reference_ecu_number", + "ecus/1057/hw_version", + "ecus/1057/logical_link", + "ecus/1057/sw_version", + "ecus/1057/zdc_version", + "ecus/1064/ecu_number", + "ecus/1064/file_identifier", + "ecus/1064/file_version", + "ecus/1064/hw_reference_ecu_number", + "ecus/1064/hw_version", + "ecus/1064/logical_link", + "ecus/1064/sw_version", + "ecus/1064/zdc_version", + "ecus/1067/ecu_number", + "ecus/1067/file_identifier", + "ecus/1067/file_version", + "ecus/1067/hw_reference_ecu_number", + "ecus/1067/hw_version", + "ecus/1067/logical_link", + "ecus/1067/sw_version", + "ecus/1067/zdc_version", + "ecus/1069/ecu_number", + "ecus/1069/file_identifier", + "ecus/1069/file_version", + "ecus/1069/hw_reference_ecu_number", + "ecus/1069/hw_version", + "ecus/1069/logical_link", + "ecus/1069/sw_version", + "ecus/1069/zdc_version", + "ecus/106F/ecu_number", + "ecus/106F/file_identifier", + "ecus/106F/file_version", + "ecus/106F/hw_reference_ecu_number", + "ecus/106F/hw_version", + "ecus/106F/logical_link", + "ecus/106F/sw_version", + "ecus/106F/zdc_version", + "ecus/1072/ecu_number", + "ecus/1072/file_identifier", + "ecus/1072/file_version", + "ecus/1072/hw_reference_ecu_number", + "ecus/1072/hw_version", + "ecus/1072/logical_link", + "ecus/1072/sw_version", + "ecus/1072/zdc_version", + "ecus/1073/ecu_number", + "ecus/1073/file_identifier", + "ecus/1073/file_version", + "ecus/1073/hw_reference_ecu_number", + "ecus/1073/hw_version", + "ecus/1073/logical_link", + "ecus/1073/sw_version", + "ecus/1073/zdc_version", + "ecus/3076/ecu_number", + "ecus/3076/file_identifier", + "ecus/3076/file_version", + "ecus/3076/hw_reference_ecu_number", + "ecus/3076/hw_version", + "ecus/3076/logical_link", + "ecus/3076/sw_version", + "ecus/3076/zdc_version", + "ecus/307B/ecu_number", + "ecus/307B/file_identifier", + "ecus/307B/file_version", + "ecus/307B/hw_reference_ecu_number", + "ecus/307B/hw_version", + "ecus/307B/logical_link", + "ecus/307B/sw_version", + "ecus/307B/zdc_version", + "ecus/307C/ecu_number", + "ecus/307C/file_identifier", + "ecus/307C/file_version", + "ecus/307C/hw_reference_ecu_number", + "ecus/307C/hw_version", + "ecus/307C/logical_link", + "ecus/307C/sw_version", + "ecus/307C/zdc_version", + "ecus/3084/ecu_number", + "ecus/3084/file_identifier", + "ecus/3084/file_version", + "ecus/3084/hw_reference_ecu_number", + "ecus/3084/hw_version", + "ecus/3084/logical_link", + "ecus/3084/sw_version", + "ecus/3084/zdc_version", + "ecus/308C/ecu_number", + "ecus/308C/file_identifier", + "ecus/308C/file_version", + "ecus/308C/hw_reference_ecu_number", + "ecus/308C/hw_version", + "ecus/308C/logical_link", + "ecus/308C/sw_version", + "ecus/308C/zdc_version", + "ecus/3096/ecu_number", + "ecus/3096/file_identifier", + "ecus/3096/file_version", + "ecus/3096/hw_reference_ecu_number", + "ecus/3096/hw_version", + "ecus/3096/logical_link", + "ecus/3096/sw_version", + "ecus/3096/zdc_version", + "ecus/3097/ecu_number", + "ecus/3097/file_identifier", + "ecus/3097/file_version", + "ecus/3097/hw_reference_ecu_number", + "ecus/3097/hw_version", + "ecus/3097/logical_link", + "ecus/3097/sw_version", + "ecus/3097/zdc_version", + "ecus/30A5/ecu_number", + "ecus/30A5/file_identifier", + "ecus/30A5/file_version", + "ecus/30A5/hw_reference_ecu_number", + "ecus/30A5/hw_version", + "ecus/30A5/logical_link", + "ecus/30A5/sw_version", + "ecus/30A5/zdc_version", + "ecus/30B8/ecu_number", + "ecus/30B8/file_identifier", + "ecus/30B8/file_version", + "ecus/30B8/hw_reference_ecu_number", + "ecus/30B8/hw_version", + "ecus/30B8/logical_link", + "ecus/30B8/sw_version", + "ecus/30B8/zdc_version", + "ecus/30B9/ecu_number", + "ecus/30B9/file_identifier", + "ecus/30B9/file_version", + "ecus/30B9/hw_reference_ecu_number", + "ecus/30B9/hw_version", + "ecus/30B9/logical_link", + "ecus/30B9/sw_version", + "ecus/30B9/zdc_version", + "ecus/30BA/ecu_number", + "ecus/30BA/file_identifier", + "ecus/30BA/file_version", + "ecus/30BA/hw_reference_ecu_number", + "ecus/30BA/hw_version", + "ecus/30BA/logical_link", + "ecus/30BA/sw_version", + "ecus/30BA/zdc_version", + "ecus/30C9/ecu_number", + "ecus/30C9/file_identifier", + "ecus/30C9/file_version", + "ecus/30C9/hw_reference_ecu_number", + "ecus/30C9/hw_version", + "ecus/30C9/logical_link", + "ecus/30C9/sw_version", + "ecus/30C9/zdc_version", + "ecus/3101/ecu_number", + "ecus/3101/file_identifier", + "ecus/3101/file_version", + "ecus/3101/hw_reference_ecu_number", + "ecus/3101/hw_version", + "ecus/3101/logical_link", + "ecus/3101/sw_version", + "ecus/3101/zdc_version", + "ecus/3102/ecu_number", + "ecus/3102/file_identifier", + "ecus/3102/file_version", + "ecus/3102/hw_reference_ecu_number", + "ecus/3102/hw_version", + "ecus/3102/logical_link", + "ecus/3102/sw_version", + "ecus/3102/zdc_version", + "ecus/3103/ecu_number", + "ecus/3103/file_identifier", + "ecus/3103/file_version", + "ecus/3103/hw_reference_ecu_number", + "ecus/3103/hw_version", + "ecus/3103/logical_link", + "ecus/3103/sw_version", + "ecus/3103/zdc_version", + "ecus/3104/ecu_number", + "ecus/3104/file_identifier", + "ecus/3104/file_version", + "ecus/3104/hw_reference_ecu_number", + "ecus/3104/hw_version", + "ecus/3104/logical_link", + "ecus/3104/sw_version", + "ecus/3104/zdc_version", + "ecus/3105/ecu_number", + "ecus/3105/file_identifier", + "ecus/3105/file_version", + "ecus/3105/hw_reference_ecu_number", + "ecus/3105/hw_version", + "ecus/3105/logical_link", + "ecus/3105/sw_version", + "ecus/3105/zdc_version", + "ecus/3106/ecu_number", + "ecus/3106/file_identifier", + "ecus/3106/file_version", + "ecus/3106/hw_reference_ecu_number", + "ecus/3106/hw_version", + "ecus/3106/logical_link", + "ecus/3106/sw_version", + "ecus/3106/zdc_version", + "ecus/3107/ecu_number", + "ecus/3107/file_identifier", + "ecus/3107/file_version", + "ecus/3107/hw_reference_ecu_number", + "ecus/3107/hw_version", + "ecus/3107/logical_link", + "ecus/3107/sw_version", + "ecus/3107/zdc_version", + "ecus/3108/ecu_number", + "ecus/3108/file_identifier", + "ecus/3108/file_version", + "ecus/3108/hw_reference_ecu_number", + "ecus/3108/hw_version", + "ecus/3108/logical_link", + "ecus/3108/sw_version", + "ecus/3108/zdc_version", + "ecus/3109/ecu_number", + "ecus/3109/file_identifier", + "ecus/3109/file_version", + "ecus/3109/hw_reference_ecu_number", + "ecus/3109/hw_version", + "ecus/3109/logical_link", + "ecus/3109/sw_version", + "ecus/3109/zdc_version", + "ecus/310C/ecu_number", + "ecus/310C/file_identifier", + "ecus/310C/file_version", + "ecus/310C/hw_reference_ecu_number", + "ecus/310C/hw_version", + "ecus/310C/logical_link", + "ecus/310C/sw_version", + "ecus/310C/zdc_version", + "ecus/3135/ecu_number", + "ecus/3135/file_identifier", + "ecus/3135/file_version", + "ecus/3135/hw_reference_ecu_number", + "ecus/3135/hw_version", + "ecus/3135/logical_link", + "ecus/3135/sw_version", + "ecus/3135/zdc_version", + "ecus/3401/ecu_number", + "ecus/3401/file_identifier", + "ecus/3401/file_version", + "ecus/3401/hw_reference_ecu_number", + "ecus/3401/hw_version", + "ecus/3401/logical_link", + "ecus/3401/sw_version", + "ecus/3401/zdc_version", + "ecus/3402/ecu_number", + "ecus/3402/file_identifier", + "ecus/3402/file_version", + "ecus/3402/hw_reference_ecu_number", + "ecus/3402/hw_version", + "ecus/3402/logical_link", + "ecus/3402/sw_version", + "ecus/3402/zdc_version", + "ecus/340E/ecu_number", + "ecus/340E/file_identifier", + "ecus/340E/file_version", + "ecus/340E/hw_reference_ecu_number", + "ecus/340E/hw_version", + "ecus/340E/logical_link", + "ecus/340E/sw_version", + "ecus/340E/zdc_version", + "ecus/3437/ecu_number", + "ecus/3437/file_identifier", + "ecus/3437/file_version", + "ecus/3437/hw_reference_ecu_number", + "ecus/3437/hw_version", + "ecus/3437/logical_link", + "ecus/3437/sw_version", + "ecus/3437/zdc_version", + "ecus/34D1/ecu_number", + "ecus/34D1/file_identifier", + "ecus/34D1/file_version", + "ecus/34D1/hw_reference_ecu_number", + "ecus/34D1/hw_version", + "ecus/34D1/logical_link", + "ecus/34D1/sw_version", + "ecus/34D1/zdc_version", + "ecus/34D5/ecu_number", + "ecus/34D5/file_identifier", + "ecus/34D5/file_version", + "ecus/34D5/hw_reference_ecu_number", + "ecus/34D5/hw_version", + "ecus/34D5/logical_link", + "ecus/34D5/sw_version", + "ecus/34D5/zdc_version", + "ecus/34D9/ecu_number", + "ecus/34D9/file_identifier", + "ecus/34D9/file_version", + "ecus/34D9/hw_reference_ecu_number", + "ecus/34D9/hw_version", + "ecus/34D9/logical_link", + "ecus/34D9/sw_version", + "ecus/34D9/zdc_version", + "ecus/34EB/ecu_number", + "ecus/34EB/file_identifier", + "ecus/34EB/file_version", + "ecus/34EB/hw_reference_ecu_number", + "ecus/34EB/hw_version", + "ecus/34EB/logical_link", + "ecus/34EB/sw_version", + "ecus/34EB/zdc_version", + "ecus/34F1/ecu_number", + "ecus/34F1/file_identifier", + "ecus/34F1/file_version", + "ecus/34F1/hw_reference_ecu_number", + "ecus/34F1/hw_version", + "ecus/34F1/logical_link", + "ecus/34F1/sw_version", + "ecus/34F1/zdc_version", + "ecus/3828/ecu_number", + "ecus/3828/file_identifier", + "ecus/3828/file_version", + "ecus/3828/hw_reference_ecu_number", + "ecus/3828/hw_version", + "ecus/3828/logical_link", + "ecus/3828/sw_version", + "ecus/3828/zdc_version", + "ecus/3829/ecu_number", + "ecus/3829/file_identifier", + "ecus/3829/file_version", + "ecus/3829/hw_reference_ecu_number", + "ecus/3829/hw_version", + "ecus/3829/logical_link", + "ecus/3829/sw_version", + "ecus/3829/zdc_version", + "ecus/4200/ecu_number", + "ecus/4200/hw_reference_ecu_number", + "ecus/4200/hw_version", + "ecus/4200/logical_link", + "ecus/4200/master_diagnostic_address", + "ecus/4200/sw_version", + "ecus/4201/ecu_number", + "ecus/4201/hw_reference_ecu_number", + "ecus/4201/hw_version", + "ecus/4201/logical_link", + "ecus/4201/master_diagnostic_address", + "ecus/4201/sw_version", + "ecus/4202/ecu_number", + "ecus/4202/hw_reference_ecu_number", + "ecus/4202/hw_version", + "ecus/4202/logical_link", + "ecus/4202/master_diagnostic_address", + "ecus/4202/sw_version", + "ecus/4203/ecu_number", + "ecus/4203/hw_reference_ecu_number", + "ecus/4203/hw_version", + "ecus/4203/logical_link", + "ecus/4203/master_diagnostic_address", + "ecus/4203/sw_version", + "ecus/4208/ecu_number", + "ecus/4208/hw_reference_ecu_number", + "ecus/4208/hw_version", + "ecus/4208/logical_link", + "ecus/4208/master_diagnostic_address", + "ecus/4208/sw_version", + "ecus/4209/ecu_number", + "ecus/4209/hw_reference_ecu_number", + "ecus/4209/hw_version", + "ecus/4209/logical_link", + "ecus/4209/master_diagnostic_address", + "ecus/4209/sw_version", + "ecus/420A/ecu_number", + "ecus/420A/hw_reference_ecu_number", + "ecus/420A/hw_version", + "ecus/420A/logical_link", + "ecus/420A/master_diagnostic_address", + "ecus/420A/sw_version", + "ecus/4215/ecu_number", + "ecus/4215/hw_reference_ecu_number", + "ecus/4215/hw_version", + "ecus/4215/logical_link", + "ecus/4215/master_diagnostic_address", + "ecus/4215/sw_version", + "ecus/4233/ecu_number", + "ecus/4233/hw_reference_ecu_number", + "ecus/4233/hw_version", + "ecus/4233/logical_link", + "ecus/4233/master_diagnostic_address", + "ecus/4233/sw_version", + "ecus/8103/ecu_number", + "ecus/8103/file_identifier", + "ecus/8103/file_version", + "ecus/8103/hw_reference_ecu_number", + "ecus/8103/hw_version", + "ecus/8103/logical_link", + "ecus/8103/sw_version", + "ecus/8103/zdc_version", + "ecus/8109/ecu_number", + "ecus/8109/file_identifier", + "ecus/8109/file_version", + "ecus/8109/hw_reference_ecu_number", + "ecus/8109/hw_version", + "ecus/8109/logical_link", + "ecus/8109/sw_version", + "ecus/8109/zdc_version", + "ecus/810A/ecu_number", + "ecus/810A/file_identifier", + "ecus/810A/file_version", + "ecus/810A/hw_reference_ecu_number", + "ecus/810A/hw_version", + "ecus/810A/logical_link", + "ecus/810A/sw_version", + "ecus/810A/zdc_version", + "ecus/810B/ecu_number", + "ecus/810B/file_identifier", + "ecus/810B/file_version", + "ecus/810B/hw_reference_ecu_number", + "ecus/810B/hw_version", + "ecus/810B/logical_link", + "ecus/810B/sw_version", + "ecus/810B/zdc_version", + "ecus/810C/ecu_number", + "ecus/810C/file_identifier", + "ecus/810C/file_version", + "ecus/810C/hw_reference_ecu_number", + "ecus/810C/hw_version", + "ecus/810C/logical_link", + "ecus/810C/sw_version", + "ecus/810C/zdc_version", + "ecus/8111/ecu_number", + "ecus/8111/file_identifier", + "ecus/8111/file_version", + "ecus/8111/hw_reference_ecu_number", + "ecus/8111/hw_version", + "ecus/8111/logical_link", + "ecus/8111/sw_version", + "ecus/8111/zdc_version", + "ecus/8112/ecu_number", + "ecus/8112/file_identifier", + "ecus/8112/file_version", + "ecus/8112/hw_reference_ecu_number", + "ecus/8112/hw_version", + "ecus/8112/logical_link", + "ecus/8112/sw_version", + "ecus/8112/zdc_version", + "ecus/8117/ecu_number", + "ecus/8117/file_identifier", + "ecus/8117/file_version", + "ecus/8117/hw_reference_ecu_number", + "ecus/8117/hw_version", + "ecus/8117/logical_link", + "ecus/8117/sw_version", + "ecus/8117/zdc_version", + "ecus/8119/ecu_number", + "ecus/8119/file_identifier", + "ecus/8119/file_version", + "ecus/8119/hw_reference_ecu_number", + "ecus/8119/hw_version", + "ecus/8119/logical_link", + "ecus/8119/sw_version", + "ecus/8119/zdc_version", + "ecus/811E/ecu_number", + "ecus/811E/file_identifier", + "ecus/811E/file_version", + "ecus/811E/hw_reference_ecu_number", + "ecus/811E/hw_version", + "ecus/811E/logical_link", + "ecus/811E/sw_version", + "ecus/811E/zdc_version", + "ecus/811F/ecu_number", + "ecus/811F/file_identifier", + "ecus/811F/file_version", + "ecus/811F/hw_reference_ecu_number", + "ecus/811F/hw_version", + "ecus/811F/logical_link", + "ecus/811F/sw_version", + "ecus/811F/zdc_version", + "ecus/8120/ecu_number", + "ecus/8120/file_identifier", + "ecus/8120/file_version", + "ecus/8120/hw_reference_ecu_number", + "ecus/8120/hw_version", + "ecus/8120/logical_link", + "ecus/8120/sw_version", + "ecus/8120/zdc_version", + "ecus/8121/ecu_number", + "ecus/8121/file_identifier", + "ecus/8121/file_version", + "ecus/8121/hw_reference_ecu_number", + "ecus/8121/hw_version", + "ecus/8121/logical_link", + "ecus/8121/sw_version", + "ecus/8121/zdc_version", + "ecus/8122/ecu_number", + "ecus/8122/file_identifier", + "ecus/8122/file_version", + "ecus/8122/hw_reference_ecu_number", + "ecus/8122/hw_version", + "ecus/8122/logical_link", + "ecus/8122/sw_version", + "ecus/8122/zdc_version", + "ecus/8124/ecu_number", + "ecus/8124/file_identifier", + "ecus/8124/file_version", + "ecus/8124/hw_reference_ecu_number", + "ecus/8124/hw_version", + "ecus/8124/logical_link", + "ecus/8124/sw_version", + "ecus/8124/zdc_version", + "ecus/8125/ecu_number", + "ecus/8125/file_identifier", + "ecus/8125/file_version", + "ecus/8125/hw_reference_ecu_number", + "ecus/8125/hw_version", + "ecus/8125/logical_link", + "ecus/8125/sw_version", + "ecus/8125/zdc_version", + "ecus/8128/ecu_number", + "ecus/8128/file_identifier", + "ecus/8128/file_version", + "ecus/8128/hw_reference_ecu_number", + "ecus/8128/hw_version", + "ecus/8128/logical_link", + "ecus/8128/sw_version", + "ecus/8128/zdc_version", + "ecus/812B/ecu_number", + "ecus/812B/file_identifier", + "ecus/812B/file_version", + "ecus/812B/hw_reference_ecu_number", + "ecus/812B/hw_version", + "ecus/812B/logical_link", + "ecus/812B/sw_version", + "ecus/812B/zdc_version", + "ecus/812C/ecu_number", + "ecus/812C/file_identifier", + "ecus/812C/file_version", + "ecus/812C/hw_reference_ecu_number", + "ecus/812C/hw_version", + "ecus/812C/logical_link", + "ecus/812C/sw_version", + "ecus/812C/zdc_version", + "ecus/812D/ecu_number", + "ecus/812D/file_identifier", + "ecus/812D/file_version", + "ecus/812D/hw_reference_ecu_number", + "ecus/812D/hw_version", + "ecus/812D/logical_link", + "ecus/812D/sw_version", + "ecus/812D/zdc_version", + "ecus/8131/ecu_number", + "ecus/8131/file_identifier", + "ecus/8131/file_version", + "ecus/8131/hw_reference_ecu_number", + "ecus/8131/hw_version", + "ecus/8131/logical_link", + "ecus/8131/sw_version", + "ecus/8131/zdc_version", + "ecus/8132/ecu_number", + "ecus/8132/file_identifier", + "ecus/8132/file_version", + "ecus/8132/hw_reference_ecu_number", + "ecus/8132/hw_version", + "ecus/8132/logical_link", + "ecus/8132/sw_version", + "ecus/8132/zdc_version", + "ecus/8133/ecu_number", + "ecus/8133/file_identifier", + "ecus/8133/file_version", + "ecus/8133/hw_reference_ecu_number", + "ecus/8133/hw_version", + "ecus/8133/logical_link", + "ecus/8133/sw_version", + "ecus/8133/zdc_version", + "ecus/8136/ecu_number", + "ecus/8136/file_identifier", + "ecus/8136/file_version", + "ecus/8136/hw_reference_ecu_number", + "ecus/8136/hw_version", + "ecus/8136/logical_link", + "ecus/8136/sw_version", + "ecus/8136/zdc_version", + "ecus/8139/ecu_number", + "ecus/8139/file_identifier", + "ecus/8139/file_version", + "ecus/8139/hw_reference_ecu_number", + "ecus/8139/hw_version", + "ecus/8139/logical_link", + "ecus/8139/sw_version", + "ecus/8139/zdc_version", + "ecus/813A/ecu_number", + "ecus/813A/file_identifier", + "ecus/813A/file_version", + "ecus/813A/hw_reference_ecu_number", + "ecus/813A/hw_version", + "ecus/813A/logical_link", + "ecus/813A/sw_version", + "ecus/813A/zdc_version", + "ecus/813B/ecu_number", + "ecus/813B/file_identifier", + "ecus/813B/file_version", + "ecus/813B/hw_reference_ecu_number", + "ecus/813B/hw_version", + "ecus/813B/logical_link", + "ecus/813B/sw_version", + "ecus/813B/zdc_version", + "ecus/813C/ecu_number", + "ecus/813C/file_identifier", + "ecus/813C/file_version", + "ecus/813C/hw_reference_ecu_number", + "ecus/813C/hw_version", + "ecus/813C/logical_link", + "ecus/813C/sw_version", + "ecus/813C/zdc_version", + "ecus/813F/ecu_number", + "ecus/813F/file_identifier", + "ecus/813F/file_version", + "ecus/813F/hw_reference_ecu_number", + "ecus/813F/hw_version", + "ecus/813F/logical_link", + "ecus/813F/sw_version", + "ecus/813F/zdc_version", + "ecus/8145/ecu_number", + "ecus/8145/file_identifier", + "ecus/8145/file_version", + "ecus/8145/hw_reference_ecu_number", + "ecus/8145/hw_version", + "ecus/8145/logical_link", + "ecus/8145/sw_version", + "ecus/8145/zdc_version", + "ecus/8146/ecu_number", + "ecus/8146/file_identifier", + "ecus/8146/file_version", + "ecus/8146/hw_reference_ecu_number", + "ecus/8146/hw_version", + "ecus/8146/logical_link", + "ecus/8146/sw_version", + "ecus/8146/zdc_version", + "ecus/8147/ecu_number", + "ecus/8147/file_identifier", + "ecus/8147/file_version", + "ecus/8147/hw_reference_ecu_number", + "ecus/8147/hw_version", + "ecus/8147/logical_link", + "ecus/8147/sw_version", + "ecus/8147/zdc_version", + "ecus/814E/ecu_number", + "ecus/814E/file_identifier", + "ecus/814E/file_version", + "ecus/814E/hw_reference_ecu_number", + "ecus/814E/hw_version", + "ecus/814E/logical_link", + "ecus/814E/sw_version", + "ecus/814E/zdc_version", + "ecus/8151/ecu_number", + "ecus/8151/file_identifier", + "ecus/8151/file_version", + "ecus/8151/hw_reference_ecu_number", + "ecus/8151/hw_version", + "ecus/8151/logical_link", + "ecus/8151/sw_version", + "ecus/8151/zdc_version", + "ecus/8152/ecu_number", + "ecus/8152/file_identifier", + "ecus/8152/file_version", + "ecus/8152/hw_reference_ecu_number", + "ecus/8152/hw_version", + "ecus/8152/logical_link", + "ecus/8152/sw_version", + "ecus/8152/zdc_version", + "ecus/8153/ecu_number", + "ecus/8153/file_identifier", + "ecus/8153/file_version", + "ecus/8153/hw_reference_ecu_number", + "ecus/8153/hw_version", + "ecus/8153/logical_link", + "ecus/8153/sw_version", + "ecus/8153/zdc_version", + "ecus/8157/ecu_number", + "ecus/8157/file_identifier", + "ecus/8157/file_version", + "ecus/8157/hw_reference_ecu_number", + "ecus/8157/hw_version", + "ecus/8157/logical_link", + "ecus/8157/sw_version", + "ecus/8157/zdc_version", + "ecus/8158/ecu_number", + "ecus/8158/file_identifier", + "ecus/8158/file_version", + "ecus/8158/hw_reference_ecu_number", + "ecus/8158/hw_version", + "ecus/8158/logical_link", + "ecus/8158/sw_version", + "ecus/8158/zdc_version", + "ecus/81D0/ecu_number", + "ecus/81D0/file_identifier", + "ecus/81D0/file_version", + "ecus/81D0/hw_reference_ecu_number", + "ecus/81D0/hw_version", + "ecus/81D0/logical_link", + "ecus/81D0/sw_version", + "ecus/81D0/zdc_version", + "embargo", + "engine_code", + "engine_code_extension", + "engines/1/engine_code", + "engines/1/engine_code_extension", + "engines/1/fuel_types/0/description", + "engines/1/fuel_types/1/description", + "engines/1/fuel_types/D/description", + "engines/1/fuel_types/E/description", + "engines/1/fuel_types/N/description", + "engines/1/fuel_types/S/description", + "engines/1/fuel_types/string/description", + "engines/2/engine_code", + "engines/2/engine_code_extension", + "engines/2/fuel_types/2/description", + "engines/engine_code", + "equipment_options/description/NZ2", + "equipment_options/description/string", + "equipment_options/description_type/NZ2", + "equipment_options/description_type/string", + "equipment_options/equipment_class/04A", + "equipment_options/equipment_class/0FA", + "equipment_options/equipment_class/0GA", + "equipment_options/equipment_class/0JE", + "equipment_options/equipment_class/0JF", + "equipment_options/equipment_class/0JG", + "equipment_options/equipment_class/0JH", + "equipment_options/equipment_class/0JJ", + "equipment_options/equipment_class/0JK", + "equipment_options/equipment_class/0JL", + "equipment_options/equipment_class/0JM", + "equipment_options/equipment_class/0K0", + "equipment_options/equipment_class/0K3", + "equipment_options/equipment_class/0K4", + "equipment_options/equipment_class/0K9", + "equipment_options/equipment_class/0KY", + "equipment_options/equipment_class/0M2", + "equipment_options/equipment_class/0M3", + "equipment_options/equipment_class/0M4", + "equipment_options/equipment_class/0N1", + "equipment_options/equipment_class/0N5", + "equipment_options/equipment_class/0P0", + "equipment_options/equipment_class/0P6", + "equipment_options/equipment_class/0RC", + "equipment_options/equipment_class/0RZ", + "equipment_options/equipment_class/0SA", + "equipment_options/equipment_class/0TA", + "equipment_options/equipment_class/0TC", + "equipment_options/equipment_class/0TD", + "equipment_options/equipment_class/0UA", + "equipment_options/equipment_class/0VA", + "equipment_options/equipment_class/0XF", + "equipment_options/equipment_class/0Y1", + "equipment_options/equipment_class/0Y5", + "equipment_options/equipment_class/0YE", + "equipment_options/equipment_class/0YF", + "equipment_options/equipment_class/0YG", + "equipment_options/equipment_class/0YH", + "equipment_options/equipment_class/0YJ", + "equipment_options/equipment_class/0YK", + "equipment_options/equipment_class/0YM", + "equipment_options/equipment_class/0YN", + "equipment_options/equipment_class/0YP", + "equipment_options/equipment_class/12D", + "equipment_options/equipment_class/1A2", + "equipment_options/equipment_class/1BA", + "equipment_options/equipment_class/1BD", + "equipment_options/equipment_class/1BE", + "equipment_options/equipment_class/1BG", + "equipment_options/equipment_class/1BK", + "equipment_options/equipment_class/1BQ", + "equipment_options/equipment_class/1BS", + "equipment_options/equipment_class/1D0", + "equipment_options/equipment_class/1EB", + "equipment_options/equipment_class/1G0", + "equipment_options/equipment_class/1G8", + "equipment_options/equipment_class/1J0", + "equipment_options/equipment_class/1J2", + "equipment_options/equipment_class/1KF", + "equipment_options/equipment_class/1KR", + "equipment_options/equipment_class/1KV", + "equipment_options/equipment_class/1LA", + "equipment_options/equipment_class/1LF", + "equipment_options/equipment_class/1LK", + "equipment_options/equipment_class/1LS", + "equipment_options/equipment_class/1LT", + "equipment_options/equipment_class/1M5", + "equipment_options/equipment_class/1MB", + "equipment_options/equipment_class/1PA", + "equipment_options/equipment_class/1PD", + "equipment_options/equipment_class/1QC", + "equipment_options/equipment_class/1SA", + "equipment_options/equipment_class/1T9", + "equipment_options/equipment_class/1VG", + "equipment_options/equipment_class/1VH", + "equipment_options/equipment_class/1X0", + "equipment_options/equipment_class/1X1", + "equipment_options/equipment_class/1X2", + "equipment_options/equipment_class/1XP", + "equipment_options/equipment_class/1XY", + "equipment_options/equipment_class/1Z0", + "equipment_options/equipment_class/1Z6", + "equipment_options/equipment_class/1ZA", + "equipment_options/equipment_class/1ZC", + "equipment_options/equipment_class/1ZD", + "equipment_options/equipment_class/1ZE", + "equipment_options/equipment_class/1ZF", + "equipment_options/equipment_class/1ZI", + "equipment_options/equipment_class/1ZM", + "equipment_options/equipment_class/20A", + "equipment_options/equipment_class/20X", + "equipment_options/equipment_class/2C5", + "equipment_options/equipment_class/2C7", + "equipment_options/equipment_class/2DI", + "equipment_options/equipment_class/2DJ", + "equipment_options/equipment_class/2EH", + "equipment_options/equipment_class/2ET", + "equipment_options/equipment_class/2EV", + "equipment_options/equipment_class/2EW", + "equipment_options/equipment_class/2EX", + "equipment_options/equipment_class/2F0", + "equipment_options/equipment_class/2F1", + "equipment_options/equipment_class/2FS", + "equipment_options/equipment_class/2H0", + "equipment_options/equipment_class/2H1", + "equipment_options/equipment_class/2H9", + "equipment_options/equipment_class/2K0", + "equipment_options/equipment_class/2K1", + "equipment_options/equipment_class/2K3", + "equipment_options/equipment_class/2K5", + "equipment_options/equipment_class/2K7", + "equipment_options/equipment_class/2MB", + "equipment_options/equipment_class/2MI", + "equipment_options/equipment_class/2MS", + "equipment_options/equipment_class/2MV", + "equipment_options/equipment_class/2V4", + "equipment_options/equipment_class/2V5", + "equipment_options/equipment_class/2V6", + "equipment_options/equipment_class/2V9", + "equipment_options/equipment_class/2W6", + "equipment_options/equipment_class/2W9", + "equipment_options/equipment_class/2WA", + "equipment_options/equipment_class/2Z0", + "equipment_options/equipment_class/2Z7", + "equipment_options/equipment_class/2Z8", + "equipment_options/equipment_class/2ZB", + "equipment_options/equipment_class/2ZC", + "equipment_options/equipment_class/2ZQ", + "equipment_options/equipment_class/31K", + "equipment_options/equipment_class/31R", + "equipment_options/equipment_class/3B5", + "equipment_options/equipment_class/3CA", + "equipment_options/equipment_class/3CX", + "equipment_options/equipment_class/3FA", + "equipment_options/equipment_class/3FP", + "equipment_options/equipment_class/3FU", + "equipment_options/equipment_class/3GD", + "equipment_options/equipment_class/3L3", + "equipment_options/equipment_class/3L5", + "equipment_options/equipment_class/3NT", + "equipment_options/equipment_class/3S0", + "equipment_options/equipment_class/3S1", + "equipment_options/equipment_class/3S2", + "equipment_options/equipment_class/3U0", + "equipment_options/equipment_class/3U4", + "equipment_options/equipment_class/3Y0", + "equipment_options/equipment_class/3Y4", + "equipment_options/equipment_class/41A", + "equipment_options/equipment_class/41I", + "equipment_options/equipment_class/44L", + "equipment_options/equipment_class/45T", + "equipment_options/equipment_class/46X", + "equipment_options/equipment_class/4A0", + "equipment_options/equipment_class/4A3", + "equipment_options/equipment_class/4A4", + "equipment_options/equipment_class/4D0", + "equipment_options/equipment_class/4D3", + "equipment_options/equipment_class/4D5", + "equipment_options/equipment_class/4E0", + "equipment_options/equipment_class/4E6", + "equipment_options/equipment_class/4E7", + "equipment_options/equipment_class/4G3", + "equipment_options/equipment_class/4GF", + "equipment_options/equipment_class/4GQ", + "equipment_options/equipment_class/4H0", + "equipment_options/equipment_class/4H3", + "equipment_options/equipment_class/4H5", + "equipment_options/equipment_class/4I7", + "equipment_options/equipment_class/4K5", + "equipment_options/equipment_class/4K6", + "equipment_options/equipment_class/4KC", + "equipment_options/equipment_class/4L1", + "equipment_options/equipment_class/4L2", + "equipment_options/equipment_class/4L6", + "equipment_options/equipment_class/4Q0", + "equipment_options/equipment_class/4UE", + "equipment_options/equipment_class/4UF", + "equipment_options/equipment_class/4ZA", + "equipment_options/equipment_class/4ZB", + "equipment_options/equipment_class/4ZD", + "equipment_options/equipment_class/4ZP", + "equipment_options/equipment_class/52T", + "equipment_options/equipment_class/52X", + "equipment_options/equipment_class/54V", + "equipment_options/equipment_class/55I", + "equipment_options/equipment_class/55J", + "equipment_options/equipment_class/56E", + "equipment_options/equipment_class/56H", + "equipment_options/equipment_class/58R", + "equipment_options/equipment_class/5C0", + "equipment_options/equipment_class/5D1", + "equipment_options/equipment_class/5F1", + "equipment_options/equipment_class/5IQ", + "equipment_options/equipment_class/5IY", + "equipment_options/equipment_class/5J0", + "equipment_options/equipment_class/5J1", + "equipment_options/equipment_class/5J3", + "equipment_options/equipment_class/5J5", + "equipment_options/equipment_class/5JA", + "equipment_options/equipment_class/5JH", + "equipment_options/equipment_class/5JJ", + "equipment_options/equipment_class/5K4", + "equipment_options/equipment_class/5K5", + "equipment_options/equipment_class/5K7", + "equipment_options/equipment_class/5L0", + "equipment_options/equipment_class/5L3", + "equipment_options/equipment_class/5MA", + "equipment_options/equipment_class/5MB", + "equipment_options/equipment_class/5MC", + "equipment_options/equipment_class/5MK", + "equipment_options/equipment_class/5MV", + "equipment_options/equipment_class/5P1", + "equipment_options/equipment_class/5P2", + "equipment_options/equipment_class/5PJ", + "equipment_options/equipment_class/5QL", + "equipment_options/equipment_class/5TG", + "equipment_options/equipment_class/5ZC", + "equipment_options/equipment_class/5ZF", + "equipment_options/equipment_class/5ZJ", + "equipment_options/equipment_class/6A0", + "equipment_options/equipment_class/6C2", + "equipment_options/equipment_class/6C4", + "equipment_options/equipment_class/6E1", + "equipment_options/equipment_class/6E3", + "equipment_options/equipment_class/6F0", + "equipment_options/equipment_class/6F4", + "equipment_options/equipment_class/6F6", + "equipment_options/equipment_class/6F7", + "equipment_options/equipment_class/6FA", + "equipment_options/equipment_class/6FC", + "equipment_options/equipment_class/6FJ", + "equipment_options/equipment_class/6FQ", + "equipment_options/equipment_class/6FW", + "equipment_options/equipment_class/6H0", + "equipment_options/equipment_class/6I3", + "equipment_options/equipment_class/6I5", + "equipment_options/equipment_class/6I6", + "equipment_options/equipment_class/6JA", + "equipment_options/equipment_class/6JD", + "equipment_options/equipment_class/6JE", + "equipment_options/equipment_class/6NJ", + "equipment_options/equipment_class/6NQ", + "equipment_options/equipment_class/6XD", + "equipment_options/equipment_class/6XK", + "equipment_options/equipment_class/6Y2", + "equipment_options/equipment_class/73A", + "equipment_options/equipment_class/76A", + "equipment_options/equipment_class/79H", + "equipment_options/equipment_class/7AA", + "equipment_options/equipment_class/7AL", + "equipment_options/equipment_class/7CR", + "equipment_options/equipment_class/7E0", + "equipment_options/equipment_class/7E6", + "equipment_options/equipment_class/7HA", + "equipment_options/equipment_class/7HB", + "equipment_options/equipment_class/7HC", + "equipment_options/equipment_class/7I4", + "equipment_options/equipment_class/7K3", + "equipment_options/equipment_class/7K6", + "equipment_options/equipment_class/7M1", + "equipment_options/equipment_class/7P0", + "equipment_options/equipment_class/7P1", + "equipment_options/equipment_class/7UF", + "equipment_options/equipment_class/7UG", + "equipment_options/equipment_class/7UI", + "equipment_options/equipment_class/7UJ", + "equipment_options/equipment_class/7UT", + "equipment_options/equipment_class/7W0", + "equipment_options/equipment_class/7W7", + "equipment_options/equipment_class/7X1", + "equipment_options/equipment_class/7Y0", + "equipment_options/equipment_class/80J", + "equipment_options/equipment_class/81X", + "equipment_options/equipment_class/81Y", + "equipment_options/equipment_class/83N", + "equipment_options/equipment_class/84B", + "equipment_options/equipment_class/84N", + "equipment_options/equipment_class/85N", + "equipment_options/equipment_class/8A5", + "equipment_options/equipment_class/8AS", + "equipment_options/equipment_class/8EX", + "equipment_options/equipment_class/8G0", + "equipment_options/equipment_class/8G1", + "equipment_options/equipment_class/8G4", + "equipment_options/equipment_class/8GU", + "equipment_options/equipment_class/8GZ", + "equipment_options/equipment_class/8I6", + "equipment_options/equipment_class/8IT", + "equipment_options/equipment_class/8IY", + "equipment_options/equipment_class/8J3", + "equipment_options/equipment_class/8J5", + "equipment_options/equipment_class/8JT", + "equipment_options/equipment_class/8M0", + "equipment_options/equipment_class/8M1", + "equipment_options/equipment_class/8QE", + "equipment_options/equipment_class/8QJ", + "equipment_options/equipment_class/8RT", + "equipment_options/equipment_class/8T2", + "equipment_options/equipment_class/8T3", + "equipment_options/equipment_class/8VG", + "equipment_options/equipment_class/8VM", + "equipment_options/equipment_class/8VP", + "equipment_options/equipment_class/8VY", + "equipment_options/equipment_class/8X1", + "equipment_options/equipment_class/8X7", + "equipment_options/equipment_class/8X8", + "equipment_options/equipment_class/8Y3", + "equipment_options/equipment_class/8Z4", + "equipment_options/equipment_class/8Z5", + "equipment_options/equipment_class/98A", + "equipment_options/equipment_class/98B", + "equipment_options/equipment_class/98C", + "equipment_options/equipment_class/98F", + "equipment_options/equipment_class/98G", + "equipment_options/equipment_class/98H", + "equipment_options/equipment_class/98K", + "equipment_options/equipment_class/98L", + "equipment_options/equipment_class/98M", + "equipment_options/equipment_class/98Q", + "equipment_options/equipment_class/98R", + "equipment_options/equipment_class/98S", + "equipment_options/equipment_class/98T", + "equipment_options/equipment_class/98V", + "equipment_options/equipment_class/98X", + "equipment_options/equipment_class/98Y", + "equipment_options/equipment_class/99A", + "equipment_options/equipment_class/99B", + "equipment_options/equipment_class/99C", + "equipment_options/equipment_class/99D", + "equipment_options/equipment_class/99E", + "equipment_options/equipment_class/99H", + "equipment_options/equipment_class/99I", + "equipment_options/equipment_class/99K", + "equipment_options/equipment_class/99M", + "equipment_options/equipment_class/99Q", + "equipment_options/equipment_class/99R", + "equipment_options/equipment_class/99T", + "equipment_options/equipment_class/99U", + "equipment_options/equipment_class/99V", + "equipment_options/equipment_class/99W", + "equipment_options/equipment_class/99X", + "equipment_options/equipment_class/99Y", + "equipment_options/equipment_class/99Z", + "equipment_options/equipment_class/9AK", + "equipment_options/equipment_class/9AQ", + "equipment_options/equipment_class/9AU", + "equipment_options/equipment_class/9B0", + "equipment_options/equipment_class/9B1", + "equipment_options/equipment_class/9G0", + "equipment_options/equipment_class/9G8", + "equipment_options/equipment_class/9I5", + "equipment_options/equipment_class/9I8", + "equipment_options/equipment_class/9JA", + "equipment_options/equipment_class/9JC", + "equipment_options/equipment_class/9JD", + "equipment_options/equipment_class/9M0", + "equipment_options/equipment_class/9M3", + "equipment_options/equipment_class/9NX", + "equipment_options/equipment_class/9P4", + "equipment_options/equipment_class/9PA", + "equipment_options/equipment_class/9PF", + "equipment_options/equipment_class/9S8", + "equipment_options/equipment_class/9S9", + "equipment_options/equipment_class/9TA", + "equipment_options/equipment_class/9TB", + "equipment_options/equipment_class/9TF", + "equipment_options/equipment_class/9VD", + "equipment_options/equipment_class/9VS", + "equipment_options/equipment_class/9WJ", + "equipment_options/equipment_class/9X0", + "equipment_options/equipment_class/9ZE", + "equipment_options/equipment_class/9ZV", + "equipment_options/equipment_class/9ZX", + "equipment_options/equipment_class/A51", + "equipment_options/equipment_class/A8F", + "equipment_options/equipment_class/A8S", + "equipment_options/equipment_class/A9F", + "equipment_options/equipment_class/AAA", + "equipment_options/equipment_class/AI0", + "equipment_options/equipment_class/AI1", + "equipment_options/equipment_class/AI8", + "equipment_options/equipment_class/AI9", + "equipment_options/equipment_class/AQ0", + "equipment_options/equipment_class/AV4", + "equipment_options/equipment_class/B01", + "equipment_options/equipment_class/B0A", + "equipment_options/equipment_class/B1P", + "equipment_options/equipment_class/B36", + "equipment_options/equipment_class/BBB", + "equipment_options/equipment_class/C00", + "equipment_options/equipment_class/C1I", + "equipment_options/equipment_class/C1Q", + "equipment_options/equipment_class/C5Q", + "equipment_options/equipment_class/C7G", + "equipment_options/equipment_class/C7T", + "equipment_options/equipment_class/C9K", + "equipment_options/equipment_class/CE1", + "equipment_options/equipment_class/CZ3", + "equipment_options/equipment_class/D14", + "equipment_options/equipment_class/D5A", + "equipment_options/equipment_class/D7P", + "equipment_options/equipment_class/D8E", + "equipment_options/equipment_class/DF9", + "equipment_options/equipment_class/E0A", + "equipment_options/equipment_class/ED6", + "equipment_options/equipment_class/EH0", + "equipment_options/equipment_class/EK0", + "equipment_options/equipment_class/EL5", + "equipment_options/equipment_class/EL8", + "equipment_options/equipment_class/EM2", + "equipment_options/equipment_class/EM3", + "equipment_options/equipment_class/ER3", + "equipment_options/equipment_class/ER6", + "equipment_options/equipment_class/ES0", + "equipment_options/equipment_class/ES4", + "equipment_options/equipment_class/ES8", + "equipment_options/equipment_class/EV0", + "equipment_options/equipment_class/F0A", + "equipment_options/equipment_class/F0Y", + "equipment_options/equipment_class/F19", + "equipment_options/equipment_class/FA5", + "equipment_options/equipment_class/FA6", + "equipment_options/equipment_class/FA8", + "equipment_options/equipment_class/FA9", + "equipment_options/equipment_class/FB0", + "equipment_options/equipment_class/FB4", + "equipment_options/equipment_class/FB5", + "equipment_options/equipment_class/FC0", + "equipment_options/equipment_class/FK0", + "equipment_options/equipment_class/FM0", + "equipment_options/equipment_class/FM7", + "equipment_options/equipment_class/FM8", + "equipment_options/equipment_class/FN0", + "equipment_options/equipment_class/FN1", + "equipment_options/equipment_class/FP0", + "equipment_options/equipment_class/FQ0", + "equipment_options/equipment_class/FQ1", + "equipment_options/equipment_class/FT0", + "equipment_options/equipment_class/FT1", + "equipment_options/equipment_class/FT4", + "equipment_options/equipment_class/FT5", + "equipment_options/equipment_class/FU2", + "equipment_options/equipment_class/FZ1", + "equipment_options/equipment_class/G1C", + "equipment_options/equipment_class/G1D", + "equipment_options/equipment_class/G1G", + "equipment_options/equipment_class/G1Z", + "equipment_options/equipment_class/GA1", + "equipment_options/equipment_class/GA2", + "equipment_options/equipment_class/GA3", + "equipment_options/equipment_class/GB0", + "equipment_options/equipment_class/GB3", + "equipment_options/equipment_class/GH0", + "equipment_options/equipment_class/GH2", + "equipment_options/equipment_class/GH4", + "equipment_options/equipment_class/GH6", + "equipment_options/equipment_class/GJ0", + "equipment_options/equipment_class/GJ4", + "equipment_options/equipment_class/GJ6", + "equipment_options/equipment_class/GJ8", + "equipment_options/equipment_class/GM0", + "equipment_options/equipment_class/GM3", + "equipment_options/equipment_class/GM4", + "equipment_options/equipment_class/GP0", + "equipment_options/equipment_class/GP4", + "equipment_options/equipment_class/GS0", + "equipment_options/equipment_class/GS5", + "equipment_options/equipment_class/GV0", + "equipment_options/equipment_class/GW2", + "equipment_options/equipment_class/GW4", + "equipment_options/equipment_class/GZ0", + "equipment_options/equipment_class/GZ2", + "equipment_options/equipment_class/H34", + "equipment_options/equipment_class/H5I", + "equipment_options/equipment_class/H7C", + "equipment_options/equipment_class/HH0", + "equipment_options/equipment_class/I53", + "equipment_options/equipment_class/I8Z", + "equipment_options/equipment_class/IT3", + "equipment_options/equipment_class/IT4", + "equipment_options/equipment_class/IU0", + "equipment_options/equipment_class/IU1", + "equipment_options/equipment_class/IU6", + "equipment_options/equipment_class/IV3", + "equipment_options/equipment_class/IW3", + "equipment_options/equipment_class/IX1", + "equipment_options/equipment_class/J1N", + "equipment_options/equipment_class/J2D", + "equipment_options/equipment_class/J9G", + "equipment_options/equipment_class/J9P", + "equipment_options/equipment_class/JH0", + "equipment_options/equipment_class/JH1", + "equipment_options/equipment_class/JS1", + "equipment_options/equipment_class/JX1", + "equipment_options/equipment_class/K4H", + "equipment_options/equipment_class/K5A", + "equipment_options/equipment_class/K8B", + "equipment_options/equipment_class/K8D", + "equipment_options/equipment_class/K8R", + "equipment_options/equipment_class/KA0", + "equipment_options/equipment_class/KA2", + "equipment_options/equipment_class/KA4", + "equipment_options/equipment_class/KA6", + "equipment_options/equipment_class/KB3", + "equipment_options/equipment_class/KB4", + "equipment_options/equipment_class/KS0", + "equipment_options/equipment_class/KS1", + "equipment_options/equipment_class/KS5", + "equipment_options/equipment_class/L0L", + "equipment_options/equipment_class/L1N", + "equipment_options/equipment_class/L1Q", + "equipment_options/equipment_class/L1S", + "equipment_options/equipment_class/L1Z", + "equipment_options/equipment_class/LH2", + "equipment_options/equipment_class/LT2", + "equipment_options/equipment_class/LW0", + "equipment_options/equipment_class/LW1", + "equipment_options/equipment_class/LX0", + "equipment_options/equipment_class/LX1", + "equipment_options/equipment_class/M0S", + "equipment_options/equipment_class/M19", + "equipment_options/equipment_class/M21", + "equipment_options/equipment_class/MEC", + "equipment_options/equipment_class/MQ3", + "equipment_options/equipment_class/N1D", + "equipment_options/equipment_class/N1H", + "equipment_options/equipment_class/N1P", + "equipment_options/equipment_class/N1X", + "equipment_options/equipment_class/N20", + "equipment_options/equipment_class/N2E", + "equipment_options/equipment_class/N2M", + "equipment_options/equipment_class/N2S", + "equipment_options/equipment_class/N3M", + "equipment_options/equipment_class/NI0", + "equipment_options/equipment_class/NI1", + "equipment_options/equipment_class/NI9", + "equipment_options/equipment_class/NJ0", + "equipment_options/equipment_class/NW0", + "equipment_options/equipment_class/NY0", + "equipment_options/equipment_class/NY2", + "equipment_options/equipment_class/NZ2", + "equipment_options/equipment_class/NZ4", + "equipment_options/equipment_class/Q09", + "equipment_options/equipment_class/Q10", + "equipment_options/equipment_class/Q11", + "equipment_options/equipment_class/Q1A", + "equipment_options/equipment_class/Q1D", + "equipment_options/equipment_class/Q4Q", + "equipment_options/equipment_class/Q8A", + "equipment_options/equipment_class/Q8B", + "equipment_options/equipment_class/Q8D", + "equipment_options/equipment_class/Q8F", + "equipment_options/equipment_class/QE1", + "equipment_options/equipment_class/QI3", + "equipment_options/equipment_class/QJ1", + "equipment_options/equipment_class/QJ3", + "equipment_options/equipment_class/QK1", + "equipment_options/equipment_class/QK3", + "equipment_options/equipment_class/QK5", + "equipment_options/equipment_class/QL1", + "equipment_options/equipment_class/QL5", + "equipment_options/equipment_class/QQ0", + "equipment_options/equipment_class/QQ1", + "equipment_options/equipment_class/QQ2", + "equipment_options/equipment_class/QQ4", + "equipment_options/equipment_class/QR9", + "equipment_options/equipment_class/QV0", + "equipment_options/equipment_class/S3N", + "equipment_options/equipment_class/S9W", + "equipment_options/equipment_class/S9X", + "equipment_options/equipment_class/SL2", + "equipment_options/equipment_class/SN8", + "equipment_options/equipment_class/string", + "equipment_options/equipment_class/T39", + "equipment_options/equipment_class/T4E", + "equipment_options/equipment_class/T4X", + "equipment_options/equipment_class/TH9", + "equipment_options/equipment_class/TI0", + "equipment_options/equipment_class/U5A", + "equipment_options/equipment_class/U9E", + "equipment_options/equipment_class/UD0", + "equipment_options/equipment_class/UD6", + "equipment_options/equipment_class/UE7", + "equipment_options/equipment_class/UE8", + "equipment_options/equipment_class/UH1", + "equipment_options/equipment_class/UH2", + "equipment_options/equipment_class/V0A", + "equipment_options/equipment_class/V39", + "equipment_options/equipment_class/V6Z", + "equipment_options/equipment_class/VC0", + "equipment_options/equipment_class/VF0", + "equipment_options/equipment_class/VF1", + "equipment_options/equipment_class/VI8", + "equipment_options/equipment_class/VJ3", + "equipment_options/equipment_class/VL0", + "equipment_options/equipment_class/VS0", + "equipment_options/equipment_class/VT2", + "equipment_options/equipment_class/VT3", + "equipment_options/equipment_class/VT5", + "equipment_options/equipment_class/VW5", + "equipment_options/equipment_class/X0A", + "equipment_options/equipment_class/X8D", + "equipment_options/equipment_class/X8E", + "equipment_options/equipment_class/X8Z", + "equipment_options/equipment_class/X9X", + "equipment_options/family/04A", + "equipment_options/family/0FA", + "equipment_options/family/0GA", + "equipment_options/family/0JE", + "equipment_options/family/0JF", + "equipment_options/family/0JG", + "equipment_options/family/0JH", + "equipment_options/family/0JJ", + "equipment_options/family/0JK", + "equipment_options/family/0JL", + "equipment_options/family/0JM", + "equipment_options/family/0K0", + "equipment_options/family/0K3", + "equipment_options/family/0K4", + "equipment_options/family/0K9", + "equipment_options/family/0KY", + "equipment_options/family/0M2", + "equipment_options/family/0M3", + "equipment_options/family/0M4", + "equipment_options/family/0N1", + "equipment_options/family/0N5", + "equipment_options/family/0P0", + "equipment_options/family/0P6", + "equipment_options/family/0RC", + "equipment_options/family/0RZ", + "equipment_options/family/0SA", + "equipment_options/family/0TA", + "equipment_options/family/0TC", + "equipment_options/family/0TD", + "equipment_options/family/0UA", + "equipment_options/family/0VA", + "equipment_options/family/0XF", + "equipment_options/family/0Y1", + "equipment_options/family/0Y5", + "equipment_options/family/0YE", + "equipment_options/family/0YF", + "equipment_options/family/0YG", + "equipment_options/family/0YH", + "equipment_options/family/0YJ", + "equipment_options/family/0YK", + "equipment_options/family/0YM", + "equipment_options/family/0YN", + "equipment_options/family/0YP", + "equipment_options/family/12D", + "equipment_options/family/1A2", + "equipment_options/family/1BA", + "equipment_options/family/1BD", + "equipment_options/family/1BE", + "equipment_options/family/1BG", + "equipment_options/family/1BK", + "equipment_options/family/1BQ", + "equipment_options/family/1BS", + "equipment_options/family/1D0", + "equipment_options/family/1EB", + "equipment_options/family/1G0", + "equipment_options/family/1G8", + "equipment_options/family/1J0", + "equipment_options/family/1J2", + "equipment_options/family/1KF", + "equipment_options/family/1KR", + "equipment_options/family/1KV", + "equipment_options/family/1LA", + "equipment_options/family/1LF", + "equipment_options/family/1LK", + "equipment_options/family/1LS", + "equipment_options/family/1LT", + "equipment_options/family/1M5", + "equipment_options/family/1MB", + "equipment_options/family/1PA", + "equipment_options/family/1PD", + "equipment_options/family/1QC", + "equipment_options/family/1SA", + "equipment_options/family/1T9", + "equipment_options/family/1VG", + "equipment_options/family/1VH", + "equipment_options/family/1X0", + "equipment_options/family/1X1", + "equipment_options/family/1X2", + "equipment_options/family/1XP", + "equipment_options/family/1XY", + "equipment_options/family/1Z0", + "equipment_options/family/1Z6", + "equipment_options/family/1ZA", + "equipment_options/family/1ZC", + "equipment_options/family/1ZD", + "equipment_options/family/1ZE", + "equipment_options/family/1ZF", + "equipment_options/family/1ZI", + "equipment_options/family/1ZM", + "equipment_options/family/20A", + "equipment_options/family/20X", + "equipment_options/family/2C5", + "equipment_options/family/2C7", + "equipment_options/family/2DI", + "equipment_options/family/2DJ", + "equipment_options/family/2EH", + "equipment_options/family/2ET", + "equipment_options/family/2EV", + "equipment_options/family/2EW", + "equipment_options/family/2EX", + "equipment_options/family/2F0", + "equipment_options/family/2F1", + "equipment_options/family/2FS", + "equipment_options/family/2H0", + "equipment_options/family/2H1", + "equipment_options/family/2H9", + "equipment_options/family/2K0", + "equipment_options/family/2K1", + "equipment_options/family/2K3", + "equipment_options/family/2K5", + "equipment_options/family/2K7", + "equipment_options/family/2MB", + "equipment_options/family/2MI", + "equipment_options/family/2MS", + "equipment_options/family/2MV", + "equipment_options/family/2V4", + "equipment_options/family/2V5", + "equipment_options/family/2V6", + "equipment_options/family/2V9", + "equipment_options/family/2W6", + "equipment_options/family/2W9", + "equipment_options/family/2WA", + "equipment_options/family/2Z0", + "equipment_options/family/2Z7", + "equipment_options/family/2Z8", + "equipment_options/family/2ZB", + "equipment_options/family/2ZC", + "equipment_options/family/2ZQ", + "equipment_options/family/31K", + "equipment_options/family/31R", + "equipment_options/family/3B5", + "equipment_options/family/3CA", + "equipment_options/family/3CX", + "equipment_options/family/3FA", + "equipment_options/family/3FP", + "equipment_options/family/3FU", + "equipment_options/family/3GD", + "equipment_options/family/3L3", + "equipment_options/family/3L5", + "equipment_options/family/3NT", + "equipment_options/family/3S0", + "equipment_options/family/3S1", + "equipment_options/family/3S2", + "equipment_options/family/3U0", + "equipment_options/family/3U4", + "equipment_options/family/3Y0", + "equipment_options/family/3Y4", + "equipment_options/family/41A", + "equipment_options/family/41I", + "equipment_options/family/44L", + "equipment_options/family/45T", + "equipment_options/family/46X", + "equipment_options/family/4A0", + "equipment_options/family/4A3", + "equipment_options/family/4A4", + "equipment_options/family/4D0", + "equipment_options/family/4D3", + "equipment_options/family/4D5", + "equipment_options/family/4E0", + "equipment_options/family/4E6", + "equipment_options/family/4E7", + "equipment_options/family/4G3", + "equipment_options/family/4GF", + "equipment_options/family/4GQ", + "equipment_options/family/4H0", + "equipment_options/family/4H3", + "equipment_options/family/4H5", + "equipment_options/family/4I7", + "equipment_options/family/4K5", + "equipment_options/family/4K6", + "equipment_options/family/4KC", + "equipment_options/family/4L1", + "equipment_options/family/4L2", + "equipment_options/family/4L6", + "equipment_options/family/4Q0", + "equipment_options/family/4UE", + "equipment_options/family/4UF", + "equipment_options/family/4ZA", + "equipment_options/family/4ZB", + "equipment_options/family/4ZD", + "equipment_options/family/4ZP", + "equipment_options/family/52T", + "equipment_options/family/52X", + "equipment_options/family/54V", + "equipment_options/family/55I", + "equipment_options/family/55J", + "equipment_options/family/56E", + "equipment_options/family/56H", + "equipment_options/family/58R", + "equipment_options/family/5C0", + "equipment_options/family/5D1", + "equipment_options/family/5F1", + "equipment_options/family/5IQ", + "equipment_options/family/5IY", + "equipment_options/family/5J0", + "equipment_options/family/5J1", + "equipment_options/family/5J3", + "equipment_options/family/5J5", + "equipment_options/family/5JA", + "equipment_options/family/5JH", + "equipment_options/family/5JJ", + "equipment_options/family/5K4", + "equipment_options/family/5K5", + "equipment_options/family/5K7", + "equipment_options/family/5L0", + "equipment_options/family/5L3", + "equipment_options/family/5MA", + "equipment_options/family/5MB", + "equipment_options/family/5MC", + "equipment_options/family/5MK", + "equipment_options/family/5MV", + "equipment_options/family/5P1", + "equipment_options/family/5P2", + "equipment_options/family/5PJ", + "equipment_options/family/5QL", + "equipment_options/family/5TG", + "equipment_options/family/5ZC", + "equipment_options/family/5ZF", + "equipment_options/family/5ZJ", + "equipment_options/family/6A0", + "equipment_options/family/6C2", + "equipment_options/family/6C4", + "equipment_options/family/6E1", + "equipment_options/family/6E3", + "equipment_options/family/6F0", + "equipment_options/family/6F4", + "equipment_options/family/6F6", + "equipment_options/family/6F7", + "equipment_options/family/6FA", + "equipment_options/family/6FC", + "equipment_options/family/6FJ", + "equipment_options/family/6FQ", + "equipment_options/family/6FW", + "equipment_options/family/6H0", + "equipment_options/family/6I3", + "equipment_options/family/6I5", + "equipment_options/family/6I6", + "equipment_options/family/6JA", + "equipment_options/family/6JD", + "equipment_options/family/6JE", + "equipment_options/family/6NJ", + "equipment_options/family/6NQ", + "equipment_options/family/6XD", + "equipment_options/family/6XK", + "equipment_options/family/6Y2", + "equipment_options/family/73A", + "equipment_options/family/76A", + "equipment_options/family/79H", + "equipment_options/family/7AA", + "equipment_options/family/7AL", + "equipment_options/family/7CR", + "equipment_options/family/7E0", + "equipment_options/family/7E6", + "equipment_options/family/7HA", + "equipment_options/family/7HB", + "equipment_options/family/7HC", + "equipment_options/family/7I4", + "equipment_options/family/7K3", + "equipment_options/family/7K6", + "equipment_options/family/7M1", + "equipment_options/family/7P0", + "equipment_options/family/7P1", + "equipment_options/family/7UF", + "equipment_options/family/7UG", + "equipment_options/family/7UI", + "equipment_options/family/7UJ", + "equipment_options/family/7UT", + "equipment_options/family/7W0", + "equipment_options/family/7W7", + "equipment_options/family/7X1", + "equipment_options/family/7Y0", + "equipment_options/family/80J", + "equipment_options/family/81X", + "equipment_options/family/81Y", + "equipment_options/family/83N", + "equipment_options/family/84B", + "equipment_options/family/84N", + "equipment_options/family/85N", + "equipment_options/family/8A5", + "equipment_options/family/8AS", + "equipment_options/family/8EX", + "equipment_options/family/8G0", + "equipment_options/family/8G1", + "equipment_options/family/8G4", + "equipment_options/family/8GU", + "equipment_options/family/8GZ", + "equipment_options/family/8I6", + "equipment_options/family/8IT", + "equipment_options/family/8IY", + "equipment_options/family/8J3", + "equipment_options/family/8J5", + "equipment_options/family/8JT", + "equipment_options/family/8M0", + "equipment_options/family/8M1", + "equipment_options/family/8QE", + "equipment_options/family/8QJ", + "equipment_options/family/8RT", + "equipment_options/family/8T2", + "equipment_options/family/8T3", + "equipment_options/family/8VG", + "equipment_options/family/8VM", + "equipment_options/family/8VP", + "equipment_options/family/8VY", + "equipment_options/family/8X1", + "equipment_options/family/8X7", + "equipment_options/family/8X8", + "equipment_options/family/8Y3", + "equipment_options/family/8Z4", + "equipment_options/family/8Z5", + "equipment_options/family/98A", + "equipment_options/family/98B", + "equipment_options/family/98C", + "equipment_options/family/98F", + "equipment_options/family/98G", + "equipment_options/family/98H", + "equipment_options/family/98K", + "equipment_options/family/98L", + "equipment_options/family/98M", + "equipment_options/family/98Q", + "equipment_options/family/98R", + "equipment_options/family/98S", + "equipment_options/family/98T", + "equipment_options/family/98V", + "equipment_options/family/98X", + "equipment_options/family/98Y", + "equipment_options/family/99A", + "equipment_options/family/99B", + "equipment_options/family/99C", + "equipment_options/family/99D", + "equipment_options/family/99E", + "equipment_options/family/99H", + "equipment_options/family/99I", + "equipment_options/family/99K", + "equipment_options/family/99M", + "equipment_options/family/99Q", + "equipment_options/family/99R", + "equipment_options/family/99T", + "equipment_options/family/99U", + "equipment_options/family/99V", + "equipment_options/family/99W", + "equipment_options/family/99X", + "equipment_options/family/99Y", + "equipment_options/family/99Z", + "equipment_options/family/9AK", + "equipment_options/family/9AQ", + "equipment_options/family/9AU", + "equipment_options/family/9B0", + "equipment_options/family/9B1", + "equipment_options/family/9G0", + "equipment_options/family/9G8", + "equipment_options/family/9I5", + "equipment_options/family/9I8", + "equipment_options/family/9JA", + "equipment_options/family/9JC", + "equipment_options/family/9JD", + "equipment_options/family/9M0", + "equipment_options/family/9M3", + "equipment_options/family/9NX", + "equipment_options/family/9P4", + "equipment_options/family/9PA", + "equipment_options/family/9PF", + "equipment_options/family/9S8", + "equipment_options/family/9S9", + "equipment_options/family/9TA", + "equipment_options/family/9TB", + "equipment_options/family/9TF", + "equipment_options/family/9VD", + "equipment_options/family/9VS", + "equipment_options/family/9WJ", + "equipment_options/family/9X0", + "equipment_options/family/9ZE", + "equipment_options/family/9ZV", + "equipment_options/family/9ZX", + "equipment_options/family/A51", + "equipment_options/family/A8F", + "equipment_options/family/A8S", + "equipment_options/family/A9F", + "equipment_options/family/AAA", + "equipment_options/family/AI0", + "equipment_options/family/AI1", + "equipment_options/family/AI8", + "equipment_options/family/AI9", + "equipment_options/family/AQ0", + "equipment_options/family/AV4", + "equipment_options/family/B01", + "equipment_options/family/B0A", + "equipment_options/family/B1P", + "equipment_options/family/B36", + "equipment_options/family/BBB", + "equipment_options/family/C00", + "equipment_options/family/C1I", + "equipment_options/family/C1Q", + "equipment_options/family/C5Q", + "equipment_options/family/C7G", + "equipment_options/family/C7T", + "equipment_options/family/C9K", + "equipment_options/family/CE1", + "equipment_options/family/CZ3", + "equipment_options/family/D14", + "equipment_options/family/D5A", + "equipment_options/family/D7P", + "equipment_options/family/D8E", + "equipment_options/family/DF9", + "equipment_options/family/E0A", + "equipment_options/family/ED6", + "equipment_options/family/EH0", + "equipment_options/family/EK0", + "equipment_options/family/EL5", + "equipment_options/family/EL8", + "equipment_options/family/EM2", + "equipment_options/family/EM3", + "equipment_options/family/ER3", + "equipment_options/family/ER6", + "equipment_options/family/ES0", + "equipment_options/family/ES4", + "equipment_options/family/ES8", + "equipment_options/family/EV0", + "equipment_options/family/F0A", + "equipment_options/family/F0Y", + "equipment_options/family/F19", + "equipment_options/family/FA5", + "equipment_options/family/FA6", + "equipment_options/family/FA8", + "equipment_options/family/FA9", + "equipment_options/family/FB0", + "equipment_options/family/FB4", + "equipment_options/family/FB5", + "equipment_options/family/FC0", + "equipment_options/family/FK0", + "equipment_options/family/FM0", + "equipment_options/family/FM7", + "equipment_options/family/FM8", + "equipment_options/family/FN0", + "equipment_options/family/FN1", + "equipment_options/family/FP0", + "equipment_options/family/FQ0", + "equipment_options/family/FQ1", + "equipment_options/family/FT0", + "equipment_options/family/FT1", + "equipment_options/family/FT4", + "equipment_options/family/FT5", + "equipment_options/family/FU2", + "equipment_options/family/FZ1", + "equipment_options/family/G1C", + "equipment_options/family/G1D", + "equipment_options/family/G1G", + "equipment_options/family/G1Z", + "equipment_options/family/GA1", + "equipment_options/family/GA2", + "equipment_options/family/GA3", + "equipment_options/family/GB0", + "equipment_options/family/GB3", + "equipment_options/family/GH0", + "equipment_options/family/GH2", + "equipment_options/family/GH4", + "equipment_options/family/GH6", + "equipment_options/family/GJ0", + "equipment_options/family/GJ4", + "equipment_options/family/GJ6", + "equipment_options/family/GJ8", + "equipment_options/family/GM0", + "equipment_options/family/GM3", + "equipment_options/family/GM4", + "equipment_options/family/GP0", + "equipment_options/family/GP4", + "equipment_options/family/GS0", + "equipment_options/family/GS5", + "equipment_options/family/GV0", + "equipment_options/family/GW2", + "equipment_options/family/GW4", + "equipment_options/family/GZ0", + "equipment_options/family/GZ2", + "equipment_options/family/H34", + "equipment_options/family/H5I", + "equipment_options/family/H7C", + "equipment_options/family/HH0", + "equipment_options/family/I53", + "equipment_options/family/I8Z", + "equipment_options/family/IT3", + "equipment_options/family/IT4", + "equipment_options/family/IU0", + "equipment_options/family/IU1", + "equipment_options/family/IU6", + "equipment_options/family/IV3", + "equipment_options/family/IW3", + "equipment_options/family/IX1", + "equipment_options/family/J1N", + "equipment_options/family/J2D", + "equipment_options/family/J9G", + "equipment_options/family/J9P", + "equipment_options/family/JH0", + "equipment_options/family/JH1", + "equipment_options/family/JS1", + "equipment_options/family/JX1", + "equipment_options/family/K4H", + "equipment_options/family/K5A", + "equipment_options/family/K8B", + "equipment_options/family/K8D", + "equipment_options/family/K8R", + "equipment_options/family/KA0", + "equipment_options/family/KA2", + "equipment_options/family/KA4", + "equipment_options/family/KA6", + "equipment_options/family/KB3", + "equipment_options/family/KB4", + "equipment_options/family/KS0", + "equipment_options/family/KS1", + "equipment_options/family/KS5", + "equipment_options/family/L0L", + "equipment_options/family/L1N", + "equipment_options/family/L1Q", + "equipment_options/family/L1S", + "equipment_options/family/L1Z", + "equipment_options/family/LH2", + "equipment_options/family/LT2", + "equipment_options/family/LW0", + "equipment_options/family/LW1", + "equipment_options/family/LX0", + "equipment_options/family/LX1", + "equipment_options/family/M0S", + "equipment_options/family/M19", + "equipment_options/family/M21", + "equipment_options/family/MEC", + "equipment_options/family/MQ3", + "equipment_options/family/N1D", + "equipment_options/family/N1H", + "equipment_options/family/N1P", + "equipment_options/family/N1X", + "equipment_options/family/N20", + "equipment_options/family/N2E", + "equipment_options/family/N2M", + "equipment_options/family/N2S", + "equipment_options/family/N3M", + "equipment_options/family/NI0", + "equipment_options/family/NI1", + "equipment_options/family/NI9", + "equipment_options/family/NJ0", + "equipment_options/family/NW0", + "equipment_options/family/NY0", + "equipment_options/family/NY2", + "equipment_options/family/NZ2", + "equipment_options/family/NZ4", + "equipment_options/family/Q09", + "equipment_options/family/Q10", + "equipment_options/family/Q11", + "equipment_options/family/Q1A", + "equipment_options/family/Q1D", + "equipment_options/family/Q4Q", + "equipment_options/family/Q8A", + "equipment_options/family/Q8B", + "equipment_options/family/Q8D", + "equipment_options/family/Q8F", + "equipment_options/family/QE1", + "equipment_options/family/QI3", + "equipment_options/family/QJ1", + "equipment_options/family/QJ3", + "equipment_options/family/QK1", + "equipment_options/family/QK3", + "equipment_options/family/QK5", + "equipment_options/family/QL1", + "equipment_options/family/QL5", + "equipment_options/family/QQ0", + "equipment_options/family/QQ1", + "equipment_options/family/QQ2", + "equipment_options/family/QQ4", + "equipment_options/family/QR9", + "equipment_options/family/QV0", + "equipment_options/family/S3N", + "equipment_options/family/S9W", + "equipment_options/family/S9X", + "equipment_options/family/SL2", + "equipment_options/family/SN8", + "equipment_options/family/string", + "equipment_options/family/T39", + "equipment_options/family/T4E", + "equipment_options/family/T4X", + "equipment_options/family/TH9", + "equipment_options/family/TI0", + "equipment_options/family/U5A", + "equipment_options/family/U9E", + "equipment_options/family/UD0", + "equipment_options/family/UD6", + "equipment_options/family/UE7", + "equipment_options/family/UE8", + "equipment_options/family/UH1", + "equipment_options/family/UH2", + "equipment_options/family/V0A", + "equipment_options/family/V39", + "equipment_options/family/V6Z", + "equipment_options/family/VC0", + "equipment_options/family/VF0", + "equipment_options/family/VF1", + "equipment_options/family/VI8", + "equipment_options/family/VJ3", + "equipment_options/family/VL0", + "equipment_options/family/VS0", + "equipment_options/family/VT2", + "equipment_options/family/VT3", + "equipment_options/family/VT5", + "equipment_options/family/VW5", + "equipment_options/family/X0A", + "equipment_options/family/X8D", + "equipment_options/family/X9X", + "equipment_options/option_code/#W3", + "equipment_options/option_code/#W5", + "equipment_options/option_code/03E", + "equipment_options/option_code/04A", + "equipment_options/option_code/04B", + "equipment_options/option_code/04C", + "equipment_options/option_code/05Z", + "equipment_options/option_code/0AD", + "equipment_options/option_code/0AE", + "equipment_options/option_code/0AG", + "equipment_options/option_code/0AH", + "equipment_options/option_code/0B1", + "equipment_options/option_code/0BC", + "equipment_options/option_code/0BD", + "equipment_options/option_code/0BE", + "equipment_options/option_code/0FA", + "equipment_options/option_code/0FS", + "equipment_options/option_code/0GA", + "equipment_options/option_code/0HZ", + "equipment_options/option_code/0JE", + "equipment_options/option_code/0JF", + "equipment_options/option_code/0JG", + "equipment_options/option_code/0JH", + "equipment_options/option_code/0JJ", + "equipment_options/option_code/0JK", + "equipment_options/option_code/0JL", + "equipment_options/option_code/0JM", + "equipment_options/option_code/0JN", + "equipment_options/option_code/0JZ", + "equipment_options/option_code/0K0", + "equipment_options/option_code/0K3", + "equipment_options/option_code/0K4", + "equipment_options/option_code/0K9", + "equipment_options/option_code/0KY", + "equipment_options/option_code/0LA", + "equipment_options/option_code/0M2", + "equipment_options/option_code/0M3", + "equipment_options/option_code/0M4", + "equipment_options/option_code/0MB", + "equipment_options/option_code/0N1", + "equipment_options/option_code/0N5", + "equipment_options/option_code/0NA", + "equipment_options/option_code/0NB", + "equipment_options/option_code/0NK", + "equipment_options/option_code/0NN", + "equipment_options/option_code/0P0", + "equipment_options/option_code/0P6", + "equipment_options/option_code/0QC", + "equipment_options/option_code/0QG", + "equipment_options/option_code/0RC", + "equipment_options/option_code/0RH", + "equipment_options/option_code/0RZ", + "equipment_options/option_code/0SA", + "equipment_options/option_code/0SM", + "equipment_options/option_code/0TA", + "equipment_options/option_code/0TC", + "equipment_options/option_code/0TD", + "equipment_options/option_code/0TE", + "equipment_options/option_code/0TS", + "equipment_options/option_code/0UA", + "equipment_options/option_code/0UB", + "equipment_options/option_code/0VA", + "equipment_options/option_code/0VC", + "equipment_options/option_code/0XF", + "equipment_options/option_code/0Y1", + "equipment_options/option_code/0Y5", + "equipment_options/option_code/0YC", + "equipment_options/option_code/0YD", + "equipment_options/option_code/0YE", + "equipment_options/option_code/0YF", + "equipment_options/option_code/0YG", + "equipment_options/option_code/0YH", + "equipment_options/option_code/0YJ", + "equipment_options/option_code/0YK", + "equipment_options/option_code/0YL", + "equipment_options/option_code/0YM", + "equipment_options/option_code/0YN", + "equipment_options/option_code/0YP", + "equipment_options/option_code/0YZ", + "equipment_options/option_code/12D", + "equipment_options/option_code/1A2", + "equipment_options/option_code/1BA", + "equipment_options/option_code/1BC", + "equipment_options/option_code/1BD", + "equipment_options/option_code/1BE", + "equipment_options/option_code/1BG", + "equipment_options/option_code/1BH", + "equipment_options/option_code/1BK", + "equipment_options/option_code/1BQ", + "equipment_options/option_code/1BS", + "equipment_options/option_code/1BV", + "equipment_options/option_code/1CV", + "equipment_options/option_code/1D0", + "equipment_options/option_code/1D9", + "equipment_options/option_code/1EB", + "equipment_options/option_code/1EJ", + "equipment_options/option_code/1ER", + "equipment_options/option_code/1FB", + "equipment_options/option_code/1G0", + "equipment_options/option_code/1G8", + "equipment_options/option_code/1I0", + "equipment_options/option_code/1J0", + "equipment_options/option_code/1J1", + "equipment_options/option_code/1J2", + "equipment_options/option_code/1JA", + "equipment_options/option_code/1JP", + "equipment_options/option_code/1KA", + "equipment_options/option_code/1KB", + "equipment_options/option_code/1KE", + "equipment_options/option_code/1KF", + "equipment_options/option_code/1KP", + "equipment_options/option_code/1KR", + "equipment_options/option_code/1KV", + "equipment_options/option_code/1KZ", + "equipment_options/option_code/1LA", + "equipment_options/option_code/1LC", + "equipment_options/option_code/1LD", + "equipment_options/option_code/1LE", + "equipment_options/option_code/1LF", + "equipment_options/option_code/1LJ", + "equipment_options/option_code/1LK", + "equipment_options/option_code/1LN", + "equipment_options/option_code/1LR", + "equipment_options/option_code/1LS", + "equipment_options/option_code/1LT", + "equipment_options/option_code/1LX", + "equipment_options/option_code/1M5", + "equipment_options/option_code/1M6", + "equipment_options/option_code/1MB", + "equipment_options/option_code/1N1", + "equipment_options/option_code/1N3", + "equipment_options/option_code/1N4", + "equipment_options/option_code/1N7", + "equipment_options/option_code/1NB", + "equipment_options/option_code/1NE", + "equipment_options/option_code/1NL", + "equipment_options/option_code/1NP", + "equipment_options/option_code/1NR", + "equipment_options/option_code/1NT", + "equipment_options/option_code/1NV", + "equipment_options/option_code/1P0", + "equipment_options/option_code/1PA", + "equipment_options/option_code/1PC", + "equipment_options/option_code/1PD", + "equipment_options/option_code/1PE", + "equipment_options/option_code/1QC", + "equipment_options/option_code/1R8", + "equipment_options/option_code/1S2", + "equipment_options/option_code/1S3", + "equipment_options/option_code/1SA", + "equipment_options/option_code/1T2", + "equipment_options/option_code/1T3", + "equipment_options/option_code/1T9", + "equipment_options/option_code/1VG", + "equipment_options/option_code/1VH", + "equipment_options/option_code/1X0", + "equipment_options/option_code/1X1", + "equipment_options/option_code/1X2", + "equipment_options/option_code/1XC", + "equipment_options/option_code/1XP", + "equipment_options/option_code/1XY", + "equipment_options/option_code/1Y0", + "equipment_options/option_code/1Y4", + "equipment_options/option_code/1Z0", + "equipment_options/option_code/1Z6", + "equipment_options/option_code/1ZA", + "equipment_options/option_code/1ZC", + "equipment_options/option_code/1ZD", + "equipment_options/option_code/1ZE", + "equipment_options/option_code/1ZF", + "equipment_options/option_code/1ZI", + "equipment_options/option_code/1ZK", + "equipment_options/option_code/1ZM", + "equipment_options/option_code/20A", + "equipment_options/option_code/20X", + "equipment_options/option_code/2C5", + "equipment_options/option_code/2C7", + "equipment_options/option_code/2D0", + "equipment_options/option_code/2D5", + "equipment_options/option_code/2D8", + "equipment_options/option_code/2DI", + "equipment_options/option_code/2DJ", + "equipment_options/option_code/2DK", + "equipment_options/option_code/2DM", + "equipment_options/option_code/2DP", + "equipment_options/option_code/2DT", + "equipment_options/option_code/2DU", + "equipment_options/option_code/2DX", + "equipment_options/option_code/2DY", + "equipment_options/option_code/2EH", + "equipment_options/option_code/2EK", + "equipment_options/option_code/2ET", + "equipment_options/option_code/2EU", + "equipment_options/option_code/2EV", + "equipment_options/option_code/2EW", + "equipment_options/option_code/2EX", + "equipment_options/option_code/2F0", + "equipment_options/option_code/2F1", + "equipment_options/option_code/2F3", + "equipment_options/option_code/2F9", + "equipment_options/option_code/2FB", + "equipment_options/option_code/2FJ", + "equipment_options/option_code/2FM", + "equipment_options/option_code/2FS", + "equipment_options/option_code/2H0", + "equipment_options/option_code/2H1", + "equipment_options/option_code/2H5", + "equipment_options/option_code/2H9", + "equipment_options/option_code/2I0", + "equipment_options/option_code/2JB", + "equipment_options/option_code/2JC", + "equipment_options/option_code/2JD", + "equipment_options/option_code/2JG", + "equipment_options/option_code/2K0", + "equipment_options/option_code/2K1", + "equipment_options/option_code/2K3", + "equipment_options/option_code/2K5", + "equipment_options/option_code/2K7", + "equipment_options/option_code/2MB", + "equipment_options/option_code/2MI", + "equipment_options/option_code/2MS", + "equipment_options/option_code/2MV", + "equipment_options/option_code/2P1", + "equipment_options/option_code/2P2", + "equipment_options/option_code/2R2", + "equipment_options/option_code/2TF", + "equipment_options/option_code/2UH", + "equipment_options/option_code/2V3", + "equipment_options/option_code/2V4", + "equipment_options/option_code/2V5", + "equipment_options/option_code/2V6", + "equipment_options/option_code/2V7", + "equipment_options/option_code/2V8", + "equipment_options/option_code/2V9", + "equipment_options/option_code/2W0", + "equipment_options/option_code/2W6", + "equipment_options/option_code/2W9", + "equipment_options/option_code/2WA", + "equipment_options/option_code/2Y1", + "equipment_options/option_code/2Y2", + "equipment_options/option_code/2Z0", + "equipment_options/option_code/2Z3", + "equipment_options/option_code/2Z7", + "equipment_options/option_code/2Z8", + "equipment_options/option_code/2ZB", + "equipment_options/option_code/2ZC", + "equipment_options/option_code/2ZJ", + "equipment_options/option_code/2ZL", + "equipment_options/option_code/2ZN", + "equipment_options/option_code/2ZQ", + "equipment_options/option_code/2ZU", + "equipment_options/option_code/31F", + "equipment_options/option_code/31K", + "equipment_options/option_code/31R", + "equipment_options/option_code/3A2", + "equipment_options/option_code/3A4", + "equipment_options/option_code/3B3", + "equipment_options/option_code/3B4", + "equipment_options/option_code/3B5", + "equipment_options/option_code/3B6", + "equipment_options/option_code/3B9", + "equipment_options/option_code/3CA", + "equipment_options/option_code/3CX", + "equipment_options/option_code/3D1", + "equipment_options/option_code/3D2", + "equipment_options/option_code/3FA", + "equipment_options/option_code/3FB", + "equipment_options/option_code/3FG", + "equipment_options/option_code/3FN", + "equipment_options/option_code/3FP", + "equipment_options/option_code/3FU", + "equipment_options/option_code/3FV", + "equipment_options/option_code/3G0", + "equipment_options/option_code/3GA", + "equipment_options/option_code/3GD", + "equipment_options/option_code/3GN", + "equipment_options/option_code/3H0", + "equipment_options/option_code/3HA", + "equipment_options/option_code/3HB", + "equipment_options/option_code/3IA", + "equipment_options/option_code/3J4", + "equipment_options/option_code/3J7", + "equipment_options/option_code/3J9", + "equipment_options/option_code/3KF", + "equipment_options/option_code/3KP", + "equipment_options/option_code/3L1", + "equipment_options/option_code/3L3", + "equipment_options/option_code/3L4", + "equipment_options/option_code/3L5", + "equipment_options/option_code/3LF", + "equipment_options/option_code/3LH", + "equipment_options/option_code/3LJ", + "equipment_options/option_code/3LT", + "equipment_options/option_code/3NS", + "equipment_options/option_code/3NT", + "equipment_options/option_code/3NU", + "equipment_options/option_code/3NZ", + "equipment_options/option_code/3PB", + "equipment_options/option_code/3PN", + "equipment_options/option_code/3PR", + "equipment_options/option_code/3Q7", + "equipment_options/option_code/3QE", + "equipment_options/option_code/3QH", + "equipment_options/option_code/3QN", + "equipment_options/option_code/3QT", + "equipment_options/option_code/3S0", + "equipment_options/option_code/3S1", + "equipment_options/option_code/3S2", + "equipment_options/option_code/3S7", + "equipment_options/option_code/3T2", + "equipment_options/option_code/3U0", + "equipment_options/option_code/3U4", + "equipment_options/option_code/3V4", + "equipment_options/option_code/3V9", + "equipment_options/option_code/3Y0", + "equipment_options/option_code/3Y4", + "equipment_options/option_code/3Y7", + "equipment_options/option_code/3ZB", + "equipment_options/option_code/3ZU", + "equipment_options/option_code/40Z", + "equipment_options/option_code/41A", + "equipment_options/option_code/41I", + "equipment_options/option_code/44L", + "equipment_options/option_code/45T", + "equipment_options/option_code/46N", + "equipment_options/option_code/46X", + "equipment_options/option_code/4A0", + "equipment_options/option_code/4A2", + "equipment_options/option_code/4A3", + "equipment_options/option_code/4A4", + "equipment_options/option_code/4AF", + "equipment_options/option_code/4D0", + "equipment_options/option_code/4D1", + "equipment_options/option_code/4D3", + "equipment_options/option_code/4D5", + "equipment_options/option_code/4D7", + "equipment_options/option_code/4E0", + "equipment_options/option_code/4E6", + "equipment_options/option_code/4E7", + "equipment_options/option_code/4G0", + "equipment_options/option_code/4G3", + "equipment_options/option_code/4GF", + "equipment_options/option_code/4GL", + "equipment_options/option_code/4GQ", + "equipment_options/option_code/4GR", + "equipment_options/option_code/4GW", + "equipment_options/option_code/4H0", + "equipment_options/option_code/4H3", + "equipment_options/option_code/4H5", + "equipment_options/option_code/4I5", + "equipment_options/option_code/4I6", + "equipment_options/option_code/4I7", + "equipment_options/option_code/4K5", + "equipment_options/option_code/4K6", + "equipment_options/option_code/4KC", + "equipment_options/option_code/4KF", + "equipment_options/option_code/4L1", + "equipment_options/option_code/4L2", + "equipment_options/option_code/4L6", + "equipment_options/option_code/4N0", + "equipment_options/option_code/4N3", + "equipment_options/option_code/4Q0", + "equipment_options/option_code/4QE", + "equipment_options/option_code/4QT", + "equipment_options/option_code/4S0", + "equipment_options/option_code/4S1", + "equipment_options/option_code/4UE", + "equipment_options/option_code/4UF", + "equipment_options/option_code/4WE", + "equipment_options/option_code/4X3", + "equipment_options/option_code/4X4", + "equipment_options/option_code/4ZA", + "equipment_options/option_code/4ZB", + "equipment_options/option_code/4ZD", + "equipment_options/option_code/4ZP", + "equipment_options/option_code/52T", + "equipment_options/option_code/52X", + "equipment_options/option_code/54N", + "equipment_options/option_code/54P", + "equipment_options/option_code/54Q", + "equipment_options/option_code/54R", + "equipment_options/option_code/54S", + "equipment_options/option_code/54T", + "equipment_options/option_code/54V", + "equipment_options/option_code/55H", + "equipment_options/option_code/55I", + "equipment_options/option_code/55J", + "equipment_options/option_code/55K", + "equipment_options/option_code/55L", + "equipment_options/option_code/56E", + "equipment_options/option_code/56F", + "equipment_options/option_code/56H", + "equipment_options/option_code/56I", + "equipment_options/option_code/57I", + "equipment_options/option_code/58G", + "equipment_options/option_code/58H", + "equipment_options/option_code/58L", + "equipment_options/option_code/58M", + "equipment_options/option_code/58R", + "equipment_options/option_code/58S", + "equipment_options/option_code/5C0", + "equipment_options/option_code/5D1", + "equipment_options/option_code/5D4", + "equipment_options/option_code/5DA", + "equipment_options/option_code/5F1", + "equipment_options/option_code/5G1", + "equipment_options/option_code/5HA", + "equipment_options/option_code/5I6", + "equipment_options/option_code/5IA", + "equipment_options/option_code/5IB", + "equipment_options/option_code/5ID", + "equipment_options/option_code/5IL", + "equipment_options/option_code/5IQ", + "equipment_options/option_code/5IY", + "equipment_options/option_code/5J0", + "equipment_options/option_code/5J1", + "equipment_options/option_code/5J3", + "equipment_options/option_code/5J5", + "equipment_options/option_code/5JA", + "equipment_options/option_code/5JB", + "equipment_options/option_code/5JH", + "equipment_options/option_code/5JJ", + "equipment_options/option_code/5K0", + "equipment_options/option_code/5K4", + "equipment_options/option_code/5K5", + "equipment_options/option_code/5K7", + "equipment_options/option_code/5KQ", + "equipment_options/option_code/5KU", + "equipment_options/option_code/5L0", + "equipment_options/option_code/5L3", + "equipment_options/option_code/5LC", + "equipment_options/option_code/5LD", + "equipment_options/option_code/5LE", + "equipment_options/option_code/5LF", + "equipment_options/option_code/5LG", + "equipment_options/option_code/5LY", + "equipment_options/option_code/5MA", + "equipment_options/option_code/5MB", + "equipment_options/option_code/5MC", + "equipment_options/option_code/5MD", + "equipment_options/option_code/5MH", + "equipment_options/option_code/5MK", + "equipment_options/option_code/5MV", + "equipment_options/option_code/5P1", + "equipment_options/option_code/5P2", + "equipment_options/option_code/5PI", + "equipment_options/option_code/5PJ", + "equipment_options/option_code/5PK", + "equipment_options/option_code/5PV", + "equipment_options/option_code/5QL", + "equipment_options/option_code/5QU", + "equipment_options/option_code/5RQ", + "equipment_options/option_code/5SL", + "equipment_options/option_code/5TB", + "equipment_options/option_code/5TD", + "equipment_options/option_code/5TE", + "equipment_options/option_code/5TF", + "equipment_options/option_code/5TG", + "equipment_options/option_code/5TK", + "equipment_options/option_code/5XJ", + "equipment_options/option_code/5ZC", + "equipment_options/option_code/5ZF", + "equipment_options/option_code/5ZJ", + "equipment_options/option_code/5ZP", + "equipment_options/option_code/65T", + "equipment_options/option_code/66E", + "equipment_options/option_code/66F", + "equipment_options/option_code/6A0", + "equipment_options/option_code/6C2", + "equipment_options/option_code/6C4", + "equipment_options/option_code/6DQ", + "equipment_options/option_code/6E1", + "equipment_options/option_code/6E2", + "equipment_options/option_code/6E3", + "equipment_options/option_code/6E7", + "equipment_options/option_code/6F0", + "equipment_options/option_code/6F2", + "equipment_options/option_code/6F4", + "equipment_options/option_code/6F6", + "equipment_options/option_code/6F7", + "equipment_options/option_code/6FA", + "equipment_options/option_code/6FC", + "equipment_options/option_code/6FG", + "equipment_options/option_code/6FH", + "equipment_options/option_code/6FJ", + "equipment_options/option_code/6FQ", + "equipment_options/option_code/6FU", + "equipment_options/option_code/6FW", + "equipment_options/option_code/6GA", + "equipment_options/option_code/6GF", + "equipment_options/option_code/6GM", + "equipment_options/option_code/6GN", + "equipment_options/option_code/6H0", + "equipment_options/option_code/6H1", + "equipment_options/option_code/6H3", + "equipment_options/option_code/6H4", + "equipment_options/option_code/6H5", + "equipment_options/option_code/6H7", + "equipment_options/option_code/6I0", + "equipment_options/option_code/6I1", + "equipment_options/option_code/6I2", + "equipment_options/option_code/6I3", + "equipment_options/option_code/6I5", + "equipment_options/option_code/6I6", + "equipment_options/option_code/6JA", + "equipment_options/option_code/6JD", + "equipment_options/option_code/6JE", + "equipment_options/option_code/6KA", + "equipment_options/option_code/6KC", + "equipment_options/option_code/6KH", + "equipment_options/option_code/6M0", + "equipment_options/option_code/6MC", + "equipment_options/option_code/6NJ", + "equipment_options/option_code/6NN", + "equipment_options/option_code/6NQ", + "equipment_options/option_code/6NV", + "equipment_options/option_code/6NZ", + "equipment_options/option_code/6P5", + "equipment_options/option_code/6RB", + "equipment_options/option_code/6RC", + "equipment_options/option_code/6W7", + "equipment_options/option_code/6XD", + "equipment_options/option_code/6XK", + "equipment_options/option_code/6XL", + "equipment_options/option_code/6XN", + "equipment_options/option_code/6XP", + "equipment_options/option_code/6XQ", + "equipment_options/option_code/6XT", + "equipment_options/option_code/6XV", + "equipment_options/option_code/6Y2", + "equipment_options/option_code/6Y4", + "equipment_options/option_code/6YD", + "equipment_options/option_code/73A", + "equipment_options/option_code/73W", + "equipment_options/option_code/76A", + "equipment_options/option_code/76C", + "equipment_options/option_code/76G", + "equipment_options/option_code/79H", + "equipment_options/option_code/7AA", + "equipment_options/option_code/7AK", + "equipment_options/option_code/7AL", + "equipment_options/option_code/7B9", + "equipment_options/option_code/7CR", + "equipment_options/option_code/7E0", + "equipment_options/option_code/7E6", + "equipment_options/option_code/7E7", + "equipment_options/option_code/7F1", + "equipment_options/option_code/7G0", + "equipment_options/option_code/7HA", + "equipment_options/option_code/7HB", + "equipment_options/option_code/7HC", + "equipment_options/option_code/7HE", + "equipment_options/option_code/7HK", + "equipment_options/option_code/7HS", + "equipment_options/option_code/7I2", + "equipment_options/option_code/7I4", + "equipment_options/option_code/7J2", + "equipment_options/option_code/7K1", + "equipment_options/option_code/7K3", + "equipment_options/option_code/7K6", + "equipment_options/option_code/7LV", + "equipment_options/option_code/7M0", + "equipment_options/option_code/7M1", + "equipment_options/option_code/7M5", + "equipment_options/option_code/7M8", + "equipment_options/option_code/7M9", + "equipment_options/option_code/7P0", + "equipment_options/option_code/7P1", + "equipment_options/option_code/7PA", + "equipment_options/option_code/7PB", + "equipment_options/option_code/7PD", + "equipment_options/option_code/7PE", + "equipment_options/option_code/7Q0", + "equipment_options/option_code/7T0", + "equipment_options/option_code/7TM", + "equipment_options/option_code/7TS", + "equipment_options/option_code/7TT", + "equipment_options/option_code/7U1", + "equipment_options/option_code/7UF", + "equipment_options/option_code/7UG", + "equipment_options/option_code/7UI", + "equipment_options/option_code/7UJ", + "equipment_options/option_code/7UT", + "equipment_options/option_code/7UY", + "equipment_options/option_code/7W0", + "equipment_options/option_code/7W1", + "equipment_options/option_code/7W2", + "equipment_options/option_code/7W7", + "equipment_options/option_code/7X1", + "equipment_options/option_code/7X2", + "equipment_options/option_code/7X5", + "equipment_options/option_code/7Y0", + "equipment_options/option_code/7Y1", + "equipment_options/option_code/7Y8", + "equipment_options/option_code/80J", + "equipment_options/option_code/81A", + "equipment_options/option_code/81X", + "equipment_options/option_code/81Y", + "equipment_options/option_code/82B", + "equipment_options/option_code/82C", + "equipment_options/option_code/82D", + "equipment_options/option_code/82H", + "equipment_options/option_code/82J", + "equipment_options/option_code/82S", + "equipment_options/option_code/83N", + "equipment_options/option_code/83Z", + "equipment_options/option_code/84B", + "equipment_options/option_code/84N", + "equipment_options/option_code/85N", + "equipment_options/option_code/8A2", + "equipment_options/option_code/8A5", + "equipment_options/option_code/8AR", + "equipment_options/option_code/8AS", + "equipment_options/option_code/8AV", + "equipment_options/option_code/8BM", + "equipment_options/option_code/8DB", + "equipment_options/option_code/8DC", + "equipment_options/option_code/8DK", + "equipment_options/option_code/8DL", + "equipment_options/option_code/8EX", + "equipment_options/option_code/8F2", + "equipment_options/option_code/8G0", + "equipment_options/option_code/8G1", + "equipment_options/option_code/8G2", + "equipment_options/option_code/8G4", + "equipment_options/option_code/8G5", + "equipment_options/option_code/8G9", + "equipment_options/option_code/8GJ", + "equipment_options/option_code/8GP", + "equipment_options/option_code/8GU", + "equipment_options/option_code/8GZ", + "equipment_options/option_code/8H5", + "equipment_options/option_code/8I4", + "equipment_options/option_code/8I5", + "equipment_options/option_code/8I6", + "equipment_options/option_code/8I9", + "equipment_options/option_code/8IR", + "equipment_options/option_code/8IT", + "equipment_options/option_code/8IU", + "equipment_options/option_code/8IV", + "equipment_options/option_code/8IX", + "equipment_options/option_code/8IY", + "equipment_options/option_code/8J3", + "equipment_options/option_code/8J5", + "equipment_options/option_code/8JT", + "equipment_options/option_code/8JU", + "equipment_options/option_code/8K1", + "equipment_options/option_code/8K8", + "equipment_options/option_code/8LA", + "equipment_options/option_code/8LE", + "equipment_options/option_code/8LH", + "equipment_options/option_code/8LU", + "equipment_options/option_code/8M0", + "equipment_options/option_code/8M1", + "equipment_options/option_code/8N5", + "equipment_options/option_code/8N6", + "equipment_options/option_code/8Q1", + "equipment_options/option_code/8Q5", + "equipment_options/option_code/8QE", + "equipment_options/option_code/8QJ", + "equipment_options/option_code/8QL", + "equipment_options/option_code/8RE", + "equipment_options/option_code/8RL", + "equipment_options/option_code/8RM", + "equipment_options/option_code/8RS", + "equipment_options/option_code/8RT", + "equipment_options/option_code/8SQ", + "equipment_options/option_code/8T2", + "equipment_options/option_code/8T3", + "equipment_options/option_code/8T6", + "equipment_options/option_code/8T8", + "equipment_options/option_code/8TL", + "equipment_options/option_code/8UN", + "equipment_options/option_code/8VG", + "equipment_options/option_code/8VJ", + "equipment_options/option_code/8VL", + "equipment_options/option_code/8VM", + "equipment_options/option_code/8VP", + "equipment_options/option_code/8VQ", + "equipment_options/option_code/8VY", + "equipment_options/option_code/8VZ", + "equipment_options/option_code/8WM", + "equipment_options/option_code/8X1", + "equipment_options/option_code/8X6", + "equipment_options/option_code/8X7", + "equipment_options/option_code/8X8", + "equipment_options/option_code/8Y0", + "equipment_options/option_code/8Y2", + "equipment_options/option_code/8Y3", + "equipment_options/option_code/8Z4", + "equipment_options/option_code/8Z5", + "equipment_options/option_code/8ZB", + "equipment_options/option_code/8ZQ", + "equipment_options/option_code/95A", + "equipment_options/option_code/95B", + "equipment_options/option_code/98A", + "equipment_options/option_code/98B", + "equipment_options/option_code/98C", + "equipment_options/option_code/98F", + "equipment_options/option_code/98G", + "equipment_options/option_code/98H", + "equipment_options/option_code/98K", + "equipment_options/option_code/98L", + "equipment_options/option_code/98M", + "equipment_options/option_code/98Q", + "equipment_options/option_code/98R", + "equipment_options/option_code/98S", + "equipment_options/option_code/98T", + "equipment_options/option_code/98V", + "equipment_options/option_code/98X", + "equipment_options/option_code/98Y", + "equipment_options/option_code/99A", + "equipment_options/option_code/99B", + "equipment_options/option_code/99C", + "equipment_options/option_code/99D", + "equipment_options/option_code/99E", + "equipment_options/option_code/99H", + "equipment_options/option_code/99I", + "equipment_options/option_code/99K", + "equipment_options/option_code/99M", + "equipment_options/option_code/99Q", + "equipment_options/option_code/99R", + "equipment_options/option_code/99T", + "equipment_options/option_code/99U", + "equipment_options/option_code/99V", + "equipment_options/option_code/99W", + "equipment_options/option_code/99X", + "equipment_options/option_code/99Y", + "equipment_options/option_code/99Z", + "equipment_options/option_code/9AH", + "equipment_options/option_code/9AK", + "equipment_options/option_code/9AQ", + "equipment_options/option_code/9AU", + "equipment_options/option_code/9B0", + "equipment_options/option_code/9B1", + "equipment_options/option_code/9DD", + "equipment_options/option_code/9DE", + "equipment_options/option_code/9G0", + "equipment_options/option_code/9G8", + "equipment_options/option_code/9I5", + "equipment_options/option_code/9I8", + "equipment_options/option_code/9IJ", + "equipment_options/option_code/9JA", + "equipment_options/option_code/9JB", + "equipment_options/option_code/9JC", + "equipment_options/option_code/9JD", + "equipment_options/option_code/9M0", + "equipment_options/option_code/9M3", + "equipment_options/option_code/9M9", + "equipment_options/option_code/9NX", + "equipment_options/option_code/9P3", + "equipment_options/option_code/9P4", + "equipment_options/option_code/9P9", + "equipment_options/option_code/9PA", + "equipment_options/option_code/9PF", + "equipment_options/option_code/9S1", + "equipment_options/option_code/9S8", + "equipment_options/option_code/9S9", + "equipment_options/option_code/9T0", + "equipment_options/option_code/9T1", + "equipment_options/option_code/9TA", + "equipment_options/option_code/9TB", + "equipment_options/option_code/9TF", + "equipment_options/option_code/9V0", + "equipment_options/option_code/9V2", + "equipment_options/option_code/9V3", + "equipment_options/option_code/9VC", + "equipment_options/option_code/9VD", + "equipment_options/option_code/9VG", + "equipment_options/option_code/9VJ", + "equipment_options/option_code/9VK", + "equipment_options/option_code/9VL", + "equipment_options/option_code/9VS", + "equipment_options/option_code/9WC", + "equipment_options/option_code/9WD", + "equipment_options/option_code/9WJ", + "equipment_options/option_code/9WT", + "equipment_options/option_code/9X0", + "equipment_options/option_code/9Z0", + "equipment_options/option_code/9Z5", + "equipment_options/option_code/9ZE", + "equipment_options/option_code/9ZK", + "equipment_options/option_code/9ZQ", + "equipment_options/option_code/9ZV", + "equipment_options/option_code/9ZX", + "equipment_options/option_code/A51", + "equipment_options/option_code/A56", + "equipment_options/option_code/A59", + "equipment_options/option_code/A8B", + "equipment_options/option_code/A8C", + "equipment_options/option_code/A8D", + "equipment_options/option_code/A8F", + "equipment_options/option_code/A8M", + "equipment_options/option_code/A8S", + "equipment_options/option_code/A9B", + "equipment_options/option_code/A9D", + "equipment_options/option_code/A9E", + "equipment_options/option_code/A9F", + "equipment_options/option_code/A9Q", + "equipment_options/option_code/AAA", + "equipment_options/option_code/AE1", + "equipment_options/option_code/AE2", + "equipment_options/option_code/AH1", + "equipment_options/option_code/AI0", + "equipment_options/option_code/AI1", + "equipment_options/option_code/AI2", + "equipment_options/option_code/AI8", + "equipment_options/option_code/AI9", + "equipment_options/option_code/AQ0", + "equipment_options/option_code/AU1", + "equipment_options/option_code/AV1", + "equipment_options/option_code/AV4", + "equipment_options/option_code/AY0", + "equipment_options/option_code/B01", + "equipment_options/option_code/B0A", + "equipment_options/option_code/B1P", + "equipment_options/option_code/B36", + "equipment_options/option_code/BBB", + "equipment_options/option_code/C00", + "equipment_options/option_code/C09", + "equipment_options/option_code/C1I", + "equipment_options/option_code/C1P", + "equipment_options/option_code/C1Q", + "equipment_options/option_code/C2K", + "equipment_options/option_code/C2R", + "equipment_options/option_code/C5Q", + "equipment_options/option_code/C7G", + "equipment_options/option_code/C7L", + "equipment_options/option_code/C7T", + "equipment_options/option_code/C9K", + "equipment_options/option_code/CA4", + "equipment_options/option_code/CC6", + "equipment_options/option_code/CE1", + "equipment_options/option_code/CM0", + "equipment_options/option_code/CN6", + "equipment_options/option_code/code", + "equipment_options/option_code/CON0", + "equipment_options/option_code/CU5", + "equipment_options/option_code/CZ2", + "equipment_options/option_code/CZ3", + "equipment_options/option_code/D14", + "equipment_options/option_code/D5A", + "equipment_options/option_code/D6C", + "equipment_options/option_code/D7F", + "equipment_options/option_code/D7M", + "equipment_options/option_code/D7P", + "equipment_options/option_code/D8E", + "equipment_options/option_code/D8S", + "equipment_options/option_code/DF9", + "equipment_options/option_code/DU4", + "equipment_options/option_code/DV2", + "equipment_options/option_code/E0A", + "equipment_options/option_code/E2D", + "equipment_options/option_code/E2E", + "equipment_options/option_code/E2I", + "equipment_options/option_code/E4U", + "equipment_options/option_code/E5L", + "equipment_options/option_code/E8S", + "equipment_options/option_code/EA0", + "equipment_options/option_code/ED6", + "equipment_options/option_code/EH0", + "equipment_options/option_code/EH1", + "equipment_options/option_code/EK0", + "equipment_options/option_code/EK2", + "equipment_options/option_code/EK4", + "equipment_options/option_code/EL1", + "equipment_options/option_code/EL2", + "equipment_options/option_code/EL3", + "equipment_options/option_code/EL4", + "equipment_options/option_code/EL5", + "equipment_options/option_code/EL8", + "equipment_options/option_code/EM1", + "equipment_options/option_code/EM2", + "equipment_options/option_code/EM3", + "equipment_options/option_code/ER1", + "equipment_options/option_code/ER3", + "equipment_options/option_code/ER5", + "equipment_options/option_code/ER6", + "equipment_options/option_code/ES0", + "equipment_options/option_code/ES4", + "equipment_options/option_code/ES7", + "equipment_options/option_code/ES8", + "equipment_options/option_code/EV0", + "equipment_options/option_code/EV3", + "equipment_options/option_code/EW0", + "equipment_options/option_code/F0A", + "equipment_options/option_code/F0Q", + "equipment_options/option_code/F0X", + "equipment_options/option_code/F0Y", + "equipment_options/option_code/F19", + "equipment_options/option_code/F4W", + "equipment_options/option_code/FA0", + "equipment_options/option_code/FA5", + "equipment_options/option_code/FA6", + "equipment_options/option_code/FA8", + "equipment_options/option_code/FA9", + "equipment_options/option_code/FB0", + "equipment_options/option_code/FB4", + "equipment_options/option_code/FB5", + "equipment_options/option_code/FB7", + "equipment_options/option_code/FC0", + "equipment_options/option_code/FI6", + "equipment_options/option_code/FI8", + "equipment_options/option_code/FK0", + "equipment_options/option_code/FM0", + "equipment_options/option_code/FM6", + "equipment_options/option_code/FM7", + "equipment_options/option_code/FM8", + "equipment_options/option_code/FN0", + "equipment_options/option_code/FN1", + "equipment_options/option_code/FP0", + "equipment_options/option_code/FP1", + "equipment_options/option_code/FQ0", + "equipment_options/option_code/FQ1", + "equipment_options/option_code/FT0", + "equipment_options/option_code/FT1", + "equipment_options/option_code/FT2", + "equipment_options/option_code/FT4", + "equipment_options/option_code/FT5", + "equipment_options/option_code/FT6", + "equipment_options/option_code/FU2", + "equipment_options/option_code/FW1", + "equipment_options/option_code/FW2", + "equipment_options/option_code/FX2", + "equipment_options/option_code/FZ0", + "equipment_options/option_code/FZ1", + "equipment_options/option_code/FZ5", + "equipment_options/option_code/G01", + "equipment_options/option_code/G03", + "equipment_options/option_code/G1A", + "equipment_options/option_code/G1C", + "equipment_options/option_code/G1D", + "equipment_options/option_code/G1G", + "equipment_options/option_code/G1Z", + "equipment_options/option_code/G8J", + "equipment_options/option_code/G8R", + "equipment_options/option_code/G9E", + "equipment_options/option_code/G9H", + "equipment_options/option_code/GA1", + "equipment_options/option_code/GA2", + "equipment_options/option_code/GA3", + "equipment_options/option_code/GB0", + "equipment_options/option_code/GB3", + "equipment_options/option_code/GH0", + "equipment_options/option_code/GH2", + "equipment_options/option_code/GH4", + "equipment_options/option_code/GH6", + "equipment_options/option_code/GJ0", + "equipment_options/option_code/GJ1", + "equipment_options/option_code/GJ2", + "equipment_options/option_code/GJ4", + "equipment_options/option_code/GJ6", + "equipment_options/option_code/GJ7", + "equipment_options/option_code/GJ8", + "equipment_options/option_code/GK1", + "equipment_options/option_code/GK2", + "equipment_options/option_code/GK2.9ZX", + "equipment_options/option_code/GM0", + "equipment_options/option_code/GM1", + "equipment_options/option_code/GM3", + "equipment_options/option_code/GM4", + "equipment_options/option_code/GP0", + "equipment_options/option_code/GP1", + "equipment_options/option_code/GP2", + "equipment_options/option_code/GP3", + "equipment_options/option_code/GP4", + "equipment_options/option_code/GS0", + "equipment_options/option_code/GS5", + "equipment_options/option_code/GT0", + "equipment_options/option_code/GT1", + "equipment_options/option_code/GT2", + "equipment_options/option_code/GT4", + "equipment_options/option_code/GT6", + "equipment_options/option_code/GT7", + "equipment_options/option_code/GV0", + "equipment_options/option_code/GV1", + "equipment_options/option_code/GW0", + "equipment_options/option_code/GW2", + "equipment_options/option_code/GW4", + "equipment_options/option_code/GZ0", + "equipment_options/option_code/GZ2", + "equipment_options/option_code/H34", + "equipment_options/option_code/H5I", + "equipment_options/option_code/H7C", + "equipment_options/option_code/HD5", + "equipment_options/option_code/HH0", + "equipment_options/option_code/HJ4", + "equipment_options/option_code/HK6", + "equipment_options/option_code/I53", + "equipment_options/option_code/I8H", + "equipment_options/option_code/I8L", + "equipment_options/option_code/I8T", + "equipment_options/option_code/I8Y", + "equipment_options/option_code/I8Z", + "equipment_options/option_code/IG0", + "equipment_options/option_code/IM0", + "equipment_options/option_code/IN0", + "equipment_options/option_code/IT1", + "equipment_options/option_code/IT3", + "equipment_options/option_code/IT4", + "equipment_options/option_code/IT5", + "equipment_options/option_code/IT6", + "equipment_options/option_code/IU0", + "equipment_options/option_code/IU1", + "equipment_options/option_code/IU3", + "equipment_options/option_code/IU6", + "equipment_options/option_code/IU7", + "equipment_options/option_code/IV0", + "equipment_options/option_code/IV3", + "equipment_options/option_code/IW1", + "equipment_options/option_code/IW2", + "equipment_options/option_code/IW3", + "equipment_options/option_code/IW5", + "equipment_options/option_code/IW6", + "equipment_options/option_code/IW7", + "equipment_options/option_code/IX1", + "equipment_options/option_code/IY0", + "equipment_options/option_code/IY1", + "equipment_options/option_code/IY2", + "equipment_options/option_code/J0H", + "equipment_options/option_code/J1H", + "equipment_options/option_code/J1N", + "equipment_options/option_code/J2B", + "equipment_options/option_code/J2D", + "equipment_options/option_code/J2D(RAH)", + "equipment_options/option_code/J2S", + "equipment_options/option_code/J34", + "equipment_options/option_code/J36", + "equipment_options/option_code/J37", + "equipment_options/option_code/J46", + "equipment_options/option_code/J47", + "equipment_options/option_code/J48", + "equipment_options/option_code/J52", + "equipment_options/option_code/J54", + "equipment_options/option_code/J55", + "equipment_options/option_code/J8K", + "equipment_options/option_code/J9B", + "equipment_options/option_code/J9C", + "equipment_options/option_code/J9D", + "equipment_options/option_code/J9G", + "equipment_options/option_code/J9I", + "equipment_options/option_code/J9P", + "equipment_options/option_code/J9X", + "equipment_options/option_code/JE3", + "equipment_options/option_code/JH0", + "equipment_options/option_code/JH1", + "equipment_options/option_code/JH2", + "equipment_options/option_code/JS1", + "equipment_options/option_code/JX0", + "equipment_options/option_code/JX1", + "equipment_options/option_code/K4H", + "equipment_options/option_code/K5A", + "equipment_options/option_code/K8B", + "equipment_options/option_code/K8C", + "equipment_options/option_code/K8D", + "equipment_options/option_code/K8G", + "equipment_options/option_code/K8K", + "equipment_options/option_code/K8R", + "equipment_options/option_code/KA0", + "equipment_options/option_code/KA2", + "equipment_options/option_code/KA4", + "equipment_options/option_code/KA6", + "equipment_options/option_code/KB2", + "equipment_options/option_code/KB3", + "equipment_options/option_code/KB4", + "equipment_options/option_code/KB8", + "equipment_options/option_code/KB9", + "equipment_options/option_code/KC0", + "equipment_options/option_code/KH4", + "equipment_options/option_code/KH5", + "equipment_options/option_code/KH7", + "equipment_options/option_code/KH8", + "equipment_options/option_code/KK1", + "equipment_options/option_code/KK2", + "equipment_options/option_code/KK3", + "equipment_options/option_code/KS0", + "equipment_options/option_code/KS1", + "equipment_options/option_code/KS3", + "equipment_options/option_code/KS5", + "equipment_options/option_code/KW0", + "equipment_options/option_code/L02", + "equipment_options/option_code/L03", + "equipment_options/option_code/L04", + "equipment_options/option_code/L06", + "equipment_options/option_code/L07", + "equipment_options/option_code/L08", + "equipment_options/option_code/L09", + "equipment_options/option_code/L0L", + "equipment_options/option_code/L10", + "equipment_options/option_code/L1E", + "equipment_options/option_code/L1F", + "equipment_options/option_code/L1G", + "equipment_options/option_code/L1I", + "equipment_options/option_code/L1L", + "equipment_options/option_code/L1N", + "equipment_options/option_code/L1Q", + "equipment_options/option_code/L1S", + "equipment_options/option_code/L1X", + "equipment_options/option_code/L1Z", + "equipment_options/option_code/LH1", + "equipment_options/option_code/LH2", + "equipment_options/option_code/LH3", + "equipment_options/option_code/LT1", + "equipment_options/option_code/LT2", + "equipment_options/option_code/LU1", + "equipment_options/option_code/LV1", + "equipment_options/option_code/LW0", + "equipment_options/option_code/LW1", + "equipment_options/option_code/LW3", + "equipment_options/option_code/LX0", + "equipment_options/option_code/LX1", + "equipment_options/option_code/LX4", + "equipment_options/option_code/LX5", + "equipment_options/option_code/M0G", + "equipment_options/option_code/M0Q", + "equipment_options/option_code/M0S", + "equipment_options/option_code/M19", + "equipment_options/option_code/M1J", + "equipment_options/option_code/M21", + "equipment_options/option_code/MEC", + "equipment_options/option_code/MQ3", + "equipment_options/option_code/N06", + "equipment_options/option_code/N07", + "equipment_options/option_code/N0A", + "equipment_options/option_code/N0B", + "equipment_options/option_code/N0C", + "equipment_options/option_code/N0U", + "equipment_options/option_code/N10", + "equipment_options/option_code/N11", + "equipment_options/option_code/N12", + "equipment_options/option_code/N15", + "equipment_options/option_code/N1D", + "equipment_options/option_code/N1H", + "equipment_options/option_code/N1P", + "equipment_options/option_code/N1S", + "equipment_options/option_code/N1X", + "equipment_options/option_code/N20", + "equipment_options/option_code/N22", + "equipment_options/option_code/N2E", + "equipment_options/option_code/N2F", + "equipment_options/option_code/N2M", + "equipment_options/option_code/N2S", + "equipment_options/option_code/N2U", + "equipment_options/option_code/N3B", + "equipment_options/option_code/N3D", + "equipment_options/option_code/N3F", + "equipment_options/option_code/N3M", + "equipment_options/option_code/N3P", + "equipment_options/option_code/N3R", + "equipment_options/option_code/N3S", + "equipment_options/option_code/N4C", + "equipment_options/option_code/N4F", + "equipment_options/option_code/N4L", + "equipment_options/option_code/N4M", + "equipment_options/option_code/N4P", + "equipment_options/option_code/N4X", + "equipment_options/option_code/N5E", + "equipment_options/option_code/N5H", + "equipment_options/option_code/N5J", + "equipment_options/option_code/N5K", + "equipment_options/option_code/N5U", + "equipment_options/option_code/N5W", + "equipment_options/option_code/N6B", + "equipment_options/option_code/N6E", + "equipment_options/option_code/N6F", + "equipment_options/option_code/N6G", + "equipment_options/option_code/N6L", + "equipment_options/option_code/N7K", + "equipment_options/option_code/N7N", + "equipment_options/option_code/N7U", + "equipment_options/option_code/NI0", + "equipment_options/option_code/NI1", + "equipment_options/option_code/NI9", + "equipment_options/option_code/NJ0", + "equipment_options/option_code/NJ2", + "equipment_options/option_code/NR0", + "equipment_options/option_code/NR1", + "equipment_options/option_code/NR2", + "equipment_options/option_code/NW0", + "equipment_options/option_code/NW2", + "equipment_options/option_code/NY0", + "equipment_options/option_code/NY2", + "equipment_options/option_code/NZ0", + "equipment_options/option_code/NZ2", + "equipment_options/option_code/NZ4", + "equipment_options/option_code/P6P", + "equipment_options/option_code/PAP", + "equipment_options/option_code/PAW", + "equipment_options/option_code/PCB", + "equipment_options/option_code/PCF", + "equipment_options/option_code/PCJ", + "equipment_options/option_code/PCX", + "equipment_options/option_code/PDL", + "equipment_options/option_code/PF3", + "equipment_options/option_code/PFD", + "equipment_options/option_code/PFL", + "equipment_options/option_code/PG4", + "equipment_options/option_code/PGP", + "equipment_options/option_code/PGS", + "equipment_options/option_code/PHP", + "equipment_options/option_code/PJ6", + "equipment_options/option_code/PLP", + "equipment_options/option_code/PMP", + "equipment_options/option_code/PNB", + "equipment_options/option_code/PSF", + "equipment_options/option_code/PSM", + "equipment_options/option_code/PSP", + "equipment_options/option_code/PT1", + "equipment_options/option_code/PT2", + "equipment_options/option_code/PT3", + "equipment_options/option_code/PT4", + "equipment_options/option_code/PT5", + "equipment_options/option_code/PT6", + "equipment_options/option_code/PT7", + "equipment_options/option_code/PT8", + "equipment_options/option_code/PT9", + "equipment_options/option_code/PTA", + "equipment_options/option_code/PTB", + "equipment_options/option_code/PTC", + "equipment_options/option_code/PTD", + "equipment_options/option_code/PTE", + "equipment_options/option_code/PTF", + "equipment_options/option_code/PTG", + "equipment_options/option_code/PTH", + "equipment_options/option_code/PTI", + "equipment_options/option_code/PTJ", + "equipment_options/option_code/PTK", + "equipment_options/option_code/PTL", + "equipment_options/option_code/PTQ", + "equipment_options/option_code/PTR", + "equipment_options/option_code/PTW", + "equipment_options/option_code/PTZ", + "equipment_options/option_code/PV3", + "equipment_options/option_code/PVZ", + "equipment_options/option_code/PW1", + "equipment_options/option_code/PW2", + "equipment_options/option_code/PWA", + "equipment_options/option_code/PWP", + "equipment_options/option_code/PX6", + "equipment_options/option_code/PX9", + "equipment_options/option_code/PXC", + "equipment_options/option_code/PYE", + "equipment_options/option_code/Q09", + "equipment_options/option_code/Q10", + "equipment_options/option_code/Q11", + "equipment_options/option_code/Q1A", + "equipment_options/option_code/Q1D", + "equipment_options/option_code/Q1G", + "equipment_options/option_code/Q1J", + "equipment_options/option_code/Q2J", + "equipment_options/option_code/Q4Q", + "equipment_options/option_code/Q8A", + "equipment_options/option_code/Q8B", + "equipment_options/option_code/Q8D", + "equipment_options/option_code/Q8F", + "equipment_options/option_code/QE0", + "equipment_options/option_code/QE1", + "equipment_options/option_code/QE3", + "equipment_options/option_code/QH1", + "equipment_options/option_code/QI3", + "equipment_options/option_code/QJ0", + "equipment_options/option_code/QJ1", + "equipment_options/option_code/QJ2", + "equipment_options/option_code/QJ3", + "equipment_options/option_code/QJ4", + "equipment_options/option_code/QJ6", + "equipment_options/option_code/QK1", + "equipment_options/option_code/QK3", + "equipment_options/option_code/QK5", + "equipment_options/option_code/QL1", + "equipment_options/option_code/QL2", + "equipment_options/option_code/QL5", + "equipment_options/option_code/QQ0", + "equipment_options/option_code/QQ1", + "equipment_options/option_code/QQ2", + "equipment_options/option_code/QQ3", + "equipment_options/option_code/QQ4", + "equipment_options/option_code/QQ5", + "equipment_options/option_code/QQ6", + "equipment_options/option_code/QQ8", + "equipment_options/option_code/QQ9", + "equipment_options/option_code/QR8", + "equipment_options/option_code/QR9", + "equipment_options/option_code/QV0", + "equipment_options/option_code/QV3", + "equipment_options/option_code/QW5", + "equipment_options/option_code/QW6", + "equipment_options/option_code/QX0", + "equipment_options/option_code/QY3", + "equipment_options/option_code/RD0", + "equipment_options/option_code/S0C", + "equipment_options/option_code/S0U", + "equipment_options/option_code/S0Z", + "equipment_options/option_code/S1K", + "equipment_options/option_code/S32", + "equipment_options/option_code/S3E", + "equipment_options/option_code/S3J", + "equipment_options/option_code/S3N", + "equipment_options/option_code/S3S", + "equipment_options/option_code/S6A", + "equipment_options/option_code/S6C", + "equipment_options/option_code/S6D", + "equipment_options/option_code/S6S", + "equipment_options/option_code/S6T", + "equipment_options/option_code/S6U", + "equipment_options/option_code/S6Y", + "equipment_options/option_code/S82", + "equipment_options/option_code/S98", + "equipment_options/option_code/S99", + "equipment_options/option_code/S9W", + "equipment_options/option_code/S9X", + "equipment_options/option_code/SE2", + "equipment_options/option_code/SE4", + "equipment_options/option_code/SJ0", + "equipment_options/option_code/SJ6", + "equipment_options/option_code/SL2", + "equipment_options/option_code/SL3", + "equipment_options/option_code/SN8", + "equipment_options/option_code/SP0", + "equipment_options/option_code/SP1", + "equipment_options/option_code/SP6", + "equipment_options/option_code/SQ0", + "equipment_options/option_code/string", + "equipment_options/option_code/SU4", + "equipment_options/option_code/SV3", + "equipment_options/option_code/SW5", + "equipment_options/option_code/T1C", + "equipment_options/option_code/T24", + "equipment_options/option_code/T38", + "equipment_options/option_code/T39", + "equipment_options/option_code/T4E", + "equipment_options/option_code/T4X", + "equipment_options/option_code/T5N", + "equipment_options/option_code/T67", + "equipment_options/option_code/T75", + "equipment_options/option_code/TH9", + "equipment_options/option_code/TI0", + "equipment_options/option_code/TR3", + "equipment_options/option_code/U4A", + "equipment_options/option_code/U5A", + "equipment_options/option_code/U5J", + "equipment_options/option_code/U60", + "equipment_options/option_code/U9B", + "equipment_options/option_code/U9C", + "equipment_options/option_code/U9E", + "equipment_options/option_code/U9H", + "equipment_options/option_code/UD0", + "equipment_options/option_code/UD1", + "equipment_options/option_code/UD2", + "equipment_options/option_code/UD6", + "equipment_options/option_code/UD7", + "equipment_options/option_code/UD8", + "equipment_options/option_code/UD9", + "equipment_options/option_code/UE7", + "equipment_options/option_code/UE8", + "equipment_options/option_code/UH1", + "equipment_options/option_code/UH2", + "equipment_options/option_code/UP1", + "equipment_options/option_code/UP3", + "equipment_options/option_code/UP9", + "equipment_options/option_code/UX6", + "equipment_options/option_code/UX7", + "equipment_options/option_code/V0A", + "equipment_options/option_code/V1F", + "equipment_options/option_code/V1N", + "equipment_options/option_code/V39", + "equipment_options/option_code/V6A", + "equipment_options/option_code/V6C", + "equipment_options/option_code/V6E", + "equipment_options/option_code/V6F", + "equipment_options/option_code/V6G", + "equipment_options/option_code/V6H", + "equipment_options/option_code/V6J", + "equipment_options/option_code/V6K", + "equipment_options/option_code/V6M", + "equipment_options/option_code/V6Z", + "equipment_options/option_code/V7A", + "equipment_options/option_code/V7C", + "equipment_options/option_code/V7D", + "equipment_options/option_code/V81", + "equipment_options/option_code/V95", + "equipment_options/option_code/VC0", + "equipment_options/option_code/VC2", + "equipment_options/option_code/VC3", + "equipment_options/option_code/VF0", + "equipment_options/option_code/VF1", + "equipment_options/option_code/VF3", + "equipment_options/option_code/VF4", + "equipment_options/option_code/VI5", + "equipment_options/option_code/VI6", + "equipment_options/option_code/VI8", + "equipment_options/option_code/VJ3", + "equipment_options/option_code/VL0", + "equipment_options/option_code/VL1", + "equipment_options/option_code/VL2", + "equipment_options/option_code/VN1", + "equipment_options/option_code/VN7", + "equipment_options/option_code/VN8", + "equipment_options/option_code/VR0", + "equipment_options/option_code/VR3", + "equipment_options/option_code/VR7", + "equipment_options/option_code/VS0", + "equipment_options/option_code/VT0", + "equipment_options/option_code/VT2", + "equipment_options/option_code/VT3", + "equipment_options/option_code/VT4", + "equipment_options/option_code/VT5", + "equipment_options/option_code/VT6", + "equipment_options/option_code/VT9", + "equipment_options/option_code/VW1", + "equipment_options/option_code/VW5", + "equipment_options/option_code/VW6", + "equipment_options/option_code/WA3", + "equipment_options/option_code/WA6", + "equipment_options/option_code/WAM", + "equipment_options/option_code/WD8", + "equipment_options/option_code/WE8", + "equipment_options/option_code/WKS", + "equipment_options/option_code/WM1", + "equipment_options/option_code/WTZ", + "equipment_options/option_code/WZH", + "equipment_options/option_code/X0A", + "equipment_options/option_code/X8D", + "equipment_options/option_code/X8E", + "equipment_options/option_code/X8Z", + "equipment_options/option_code/X9S", + "equipment_options/option_code/X9X", + "equipment_options/option_code/YEA", + "equipment_options/option_code/YEB", + "equipment_options/option_code/YEC", + "equipment_options/option_code/YED", + "equipment_options/option_code/YEE", + "equipment_options/option_code/YEF", + "equipment_options/option_code/YEG", + "equipment_options/option_code/YEH", + "equipment_options/option_code/YEZ", + "equipment_options/option_code/YJ1", + "equipment_options/option_code/YJA", + "equipment_options/option_code/YX1", + "equipment_options/testkey", + "et/startuptime", + "fsid", + "fsid_function_pnr", + "GA2", + "gdc/10272/name", + "gdc/10272/version", + "gdc/12304/name", + "gdc/12304/version", + "gdc/12545/name", + "gdc/12545/version", + "gdc/257/name", + "gdc/257/version", + "gdc/258/name", + "gdc/258/version", + "gdc/259/name", + "gdc/259/version", + "gdc/4113/name", + "gdc/4113/version", + "gdc/4129/name", + "gdc/4129/version", + "gdc/4161/name", + "gdc/4161/version", + "gdc/4177/name", + "gdc/4177/version", + "gdc/4353/name", + "gdc/4353/version", + "gdc/8192/name", + "gdc/8192/version", + "gdc/8448/name", + "gdc/8448/version", + "gdc/8464/name", + "gdc/8464/version", + "gdc/8480/name", + "gdc/8480/version", + "gdc/8496/name", + "gdc/8496/version", + "gdc/8512/name", + "gdc/8512/version", + "gdc/8528/name", + "gdc/8528/version", + "gdc/8704/name", + "gdc/8704/version", + "gdc/dcMasterVersion", + "hcp3_software_version", + "isVirtual", + "lifeData/timeLine/production_date", + "mmi", + "model/model_codes", + "model/model_description", + "model/model_name", + "model/model_year", + "model_code", + "model_family", + "model_name", + "model_year", + "platform_name", + "platform_variant", + "pnr_list", + "production_date", + "result", + "resultDescription", + "sim/euiccid", + "sim/iccid", + "sim/imei", + "sim/imsi", + "state/testkey", + "sumotest", + "synthetic", + "test", + "test1", + "test2", + "testkey", + "timestamp", + "vehicle_id", + "vehicleId", + "vehicleOrgLevel1", + "vehicleOrgLevel2", + "vehicleOrgLevel3", + "vehiclePlatform", + "vin" + ] +} \ No newline at end of file diff --git a/src/main/resources/kafka_client.p12 b/src/main/resources/kafka_client.p12 new file mode 100644 index 0000000000000000000000000000000000000000..df6f94ca0ceb53c16e93367b1626e8c5ca64e1ac GIT binary patch literal 6230 zcmY+IRZtv^l7(S_!5K6R?hrzW87+cAei3v4eR}2@+Ge~hssYaTh(IKJKpm6X&bhoh=XC1u|?bx1=mM4X69!H%GpI`hq5n=8XO1ZrQd7?p1xYi9j3IKLJgfffQTVC z+ri%W;qLh_*)xp$R#DdP>bj5LuzM%THed&WV%e_Jf8UV%v#WY!G&|8xRFKSeOwjAa zT4QL&!VpZDn2)G%L*`E3(*dQUaqR8GknT&y)KbxB48aN-i8RDd6mehICEh(+L+3!; zvp=mDy@~mOueY1DLrSs-mJ6F1;9x?Z5kRAV@X3yl+y{;;Xd7Xv1}$Hwzu)ZtKt3X9DEhkaEXdjPWB3ZH(1`5&D=xLH#OnLovVDpRkk@>K4QmBi zG;RNLrttNmYoxkC0sl@=BcHQR|H4(H!Q9SufucW`t2T36yEHP%Svw{W>@(5@P6Ek zRs1eex)#R+$|Ku8jA7gqHzeM(1s(KOo?hA{#99)h>4)T2W_J0Ahk=3EY(T<#h33Te z98M|gQ_UtdcRe@Td*S-?d1Ro1b3?7TSzO|dfQb@+Rps)KiYq_U!Momytx&nrTq%z~ zPuBS9mZHR@tyz{A<82ADoLvnAM|z_uSHEr(WT%_dsU9ywg1^dvX7x7hx*bEtI50jO zy%{j)cpXR_;jg#mqNs^yV27g_@*&cUn>1)MX0z@@2VI$q)D|$0VWT$~$zW90+)=d@ zHP`M1CH7#dDxAJ3t5u=EhcB3|W9JM+xzsS4&p9|x#2ZBqZ-nS7IK?Q3ke{jNm%bb> z(Z0*|?MDa}pT9hFtw6(II-${)JX#^I!+e@C(v1SoRck9#OXEyQQ6-3~Dxg~?*;gCV z6O}8GQFPo?idL+ScP-R-J_gg{!DIN)LF+*Vw&U867}G2QAb8vvfh+MZZhxOg7q52b z7^|MbTRxIC@y~47H6_ffk_-S%ILIRlUexIWJn58D~* zIXp~188yKdRg9sZlDedlQxFS8z>pDsov2jh#6-IzP)uwjZQ7~9LWY*yI=f7X*KGkONSV_V})6KZ!n4ZNXDhQBsDayWiVS+ z!t;kGZM==?=6nhF5@Z>R+}bcU*l22;8@^^fKGs=*-!;O4R4F$WZN74fhI`E{4|<)cxjLra0@`6|zYaxN+$`7vnE6Jt-&p z84|EOS6s7E(#Wvf)HS&SWI{PqI;Ecze;2HU0b9{nY2<6Q;nn~mlT;!S7!<1qvufxw9j-H?7+yQpzKqinN4H=Ao^t9I z8S&?}3nD5=)@Pyhyx6P7%TXM%{eA@#Gti=a94$GZ^h4jZH>*@6!bp>(QyP@%I#>G3 zJV`?M&C(x!0vG*qjT|XQ*eBAYpNNeH4Bx&4(ynnHZ$DL^+8f{btI_#>aLQ%-Cc3MN z;7auf=33hO?AT*ptP+GC;$EuDa58=GoKH2+71tMvK{9A>nFq50*D-}9CKQZ ze<(@#Wlwh43N1WoPU59>x`iesfojQEjAva?jqOk@Q=~d~Fi;dd;dX=;#{0gfV|lU% zk1KKWy|Q!p6jWhHzh2CA!hTAVq2U(7A#s4=Rzl74{=W873}F+riv zUQk{;TN|72(TXmdjwFe2I{o+N+WKdeY*{imot)+Y938HEtrDoph8E$$aP{S$|%pjfP4#nAUE z>i1b-t?vrs;Qd+SCI2uLwV(m-H`DF_&m{_uhJT)F+v|ha5|yhD?V5@2g-{hFV6OkJ zgE*Aq@M8>&iRB|HcY|G_sBm1lRb|AKw(2i?0}ReBq8hy2rI1n`NY`xZ@0EFC{`Dy3 zU5xiQ3rV0c18M=~b*cGWLtN|YywQm-pSD}bIkQZY3qP-hEKb=}hd4Hp{?HOqU~Ncq zrl0-mpukt*r5zz9tEJ97eTnaZ87u8bwD*W7?rukDbmmyWy^2aznI9|a7H4jhHMof& zPP2}5pf^~BbLD#tqSJM*r~#L0CpMlj&kz3^zW|>Z?&^!ss8$Yj^m>vXXQvVL#r}@B z%&A{Q?~2?T(CI9K9L@?|!(O@Ag{w-`I3o9w5iqDD)PkpG6R+b^VTW0xfDze<9kt`3 z1+nP~rk6i|Fsx>J77>0C^ZUxL!(I{*UN64O1Lw9M+ALa_TQ*3QUcGpAg06P*$uq`i z6vZ+wMhrsfZ{|}kMR-#Ce3Cee5xK_SmgwUSna5A8+hTR>PZN90P)-dhsgIDjk@3#)tp%c_C{nd8*K_aO-h*l=TV!MQ7+usHN$F)$LINni* z=J!5h)`1JHhiKh<#XZ#b1;=IN*+xX|T)Y@RU2KesifX()ksi}!?%@rZ$M_%1LDQ+3 z294xb5t*rz0!4iC5^YK6tJc`B3!__0C*5mkI(TuWPo3YNX)@^tGbli?>gQ_}bmKg9 zWEKLy`%kVjMny1;;NxNBIEv;+Gi;sO;IxbQ?pQV>rYEB8Ikn2r+@5 zB>Ec~wSQQyeC{=sF)jlsA*Hs~S|dI3E}{himqre}2!bf~>OGHWkJ8I;c~jGGM>@S} zGdt{MF{(@-C zXj@2Wz(9uB9m>RpMLy}<5^3Nb!O%7#!^XtnDX63N79v7B(2z|ZzHIp;)FKG^;~tyu z5}p>^2I3L1qOz0@J^%Hpz>w-U2Unn|51WmwsWm~Hl86WSg~fW!6#R5nL;Mj!gx-%P zN|IKmnGx8J<}vvQFVwmXkQTcdh(t)fHdNl(F^g$+oHASgxd6 z)NF%~^dr5@BRqoplwue=$I8V^dThSWR4T?;{VUx`$@|SXD;~b}yoNTCy11B00$p;% zp^GLg16vxwScoO89nT}SsZD2jd@)9^)nM)K$9 zky)BLF^8#Hi+NOQw_>_;Riq0(yGcl5BnsCBpYh=3k2JL~Kw(P>3bsq%{?f)`_Z{ey zy2LLbW|4r*@v1ddzQ^i%zj60J*w{fQz$(a=No*XGM@&(kivriPbV{phab5 z=Zh;v#~?AW>j#=OCWO29#jD3DNYY5Fc|WUHJF(b=IfDOGPa{rhA`G$XP9esA0oA-anG$)B8InB-k=faT?h>|dN{2)Vkq!ZtB-vt%0yPUQ8jSgMBQ zM~>)Dq+fLAu8v&yDxDF5uhcD4b!HvpvhdZ9M|)8R5raN5RGe7Zw=D{|i0lF%a@;|@ zy4$`ZHaPx|K*UWYQ6!HxNq660fnA08DL0*tGa@&}pF3T0#+h^`NF9vIw->iv)~rMR z)?P?B%7>)xk)lVtjn}QXv{N1>*Qvcui#5zbQiNi2zLrhjM3A7(Sr+A_YDdZ~B3Yah z(4nil6dBY#o0A;{>CQYR_rzP!5c)Gak)PPf+qSs(9;#5#hDC*hpJ7Vj^a4eF{4VGc-s3*^LrD&svSTM6g=5k3a>J} zO{vl^H0NwoW7m5ht}#?6lHL6C-4@3bZ)6V)?Gr;1q)-n#I~w zSe-w7ms6oDW?}M0OmszjuxUR*e2_eufnEB+NKzg#-I{TsyOm_ zG>S@g2SyyyiV(@85{^&NT8B;B{w{%aM5_N3Pw?RS$&QOO$7FvRnq9ugai1}j_`}K77l!;$^aJh?pq_UqA9CE7N4XoTj=p3Eu3}zJ@{^x| zdY!;bsCw1qW0Orzd@;Y(0|Q)%ZkO)ZtD@gwER>EmTp2o$j0cty;E>rhPAaCGeRU8> z7>@~mM9tvUJGA0?&O|Lb7#f)b3kwj=%hP>du+0daq(~|V;QH(Q;oR!hQbukvQB!8{ z4Hv7jwCr~PL@!z&K~-Ilpn}|%g=)IsnqL!uQIpNHE_iw$(=e>Uc>;A2ZSxu?p4Hl2 zgU^`(`q6(Z8>3?18>^Zc?DBBD{tLVD#a8Kc5Dbd5-ZQlliXcBPT=QOsK#}bK4|vLl zA{in=k#zr&HUBA9Ao~AcC^UFLJ{0jB0!2Lje{>4r-*n0wt5+;Mx9srWbP5rQIFibx zIV3iAy5`~>y*+0AT(oO9{$X&IoHDq+wtTSr>#c%6b;5I8U*N+q zPL!%ieHnr!>oHa!ee=k+oYiattcOj@+^x0V8#-X}I6-FZ`KZ+a-+bVog;M@^%3mRd zf>7VaKlkdW_KzuDy9rr!K13FsQ?4ItOLVJ0h88BB`+Rxrlr^01^D!N^9C0QfP`qwA z)?6j@vk7NF$>)pE=n>a+WXb(zFoV51&Alkl2S6S~D0eVY^ohGc=%B)1)IE^`>4gA6 z*D@|OU05*4(JPKK8|i~4Y@n-VGd8Qx*m+`qgl&IiH$a8Qvfe~~{vt^#+^D3X0Q>rC zg&==%7k6%{_X>b(l`L@bGkdw`rPt5P6xrdG9l5sfoc^|@0-es+QrJ|hcWycb$NW-D zo*{hK)AF^hJo#u#ZT)YWiaBEi`cd<=nHitxsZ=AtFFChA>vyf%S2Fj4fF`% zrS_Oc_L{N9&>p84n+X+G)I?B!9>GkOnWLiaKm^uxwg2I0sJsfw2Uz|dU zM|NkU&g`3)8|pNWr@2lkuI<3G-X_8A*IUfe46Fg2B*2w8aC5LpLj=XF zG`quG*N-~dcU0C9(aO8y6lJ?tHzO@*@3wo9@{3h&Crsy+r0iHd`F?Du6YK_R2eI+V zKB-anZ3W(%-p}ibs24o_c5aXBXlx3%YdId`Wr2uEnkFYpix%-jtZQ0sFn0J&P>T|b);061gJI-Bm48DbL4bh(|0!u8TZTW08@%o zzW{`pn3wq750)5S?~AgI?ebL4Q;DqGZ0U0WP|BQzj>-WZtj@jo!L|D}rT0SN*@{Xn zQv{p%TF1mspDZ&-AJ(cWiHqCN$hQ-LVUCWRKuG&I&UxO=zP;Zfoqx7&9T)B|$7&Ub zBF+Bkmmu_`ab@gDbD^YD0!lW{O8pY1zKnsZF%B~J-x2nd!gHBf6u9ZA(Ra+hNOM$3 zGk=aZj2}ao(?4l$5~&DwhjWwKeTW25G=}yl4vbngjt=(j5K_ZxHkblSVoZnS2tW3J z&Xovf$l#%vdG>e+xaP{o(d+ApRU*sMs~nnePWISaGYzBB33xVJ_SYWc)BM0m`SCeU zo_1j!uX;}!x$XtmMFb&bv*`C${Kz`}lDxrEM;iW(NZa0Kh1v;SXwLn?m0Rn=r>w`_ zm+74&<1M8FvpCl|VVp!8!uU@X0i!Ofo1_JjyR)OTYTg|2t0q1y@DZXaE2J literal 0 HcmV?d00001 diff --git a/src/main/resources/kafka_client.pem b/src/main/resources/kafka_client.pem new file mode 100644 index 0000000..92bda59 --- /dev/null +++ b/src/main/resources/kafka_client.pem @@ -0,0 +1,116 @@ +subject=C = CN, O = VW China, CN = qa.mdmds.maezia.com + +issuer=DC = com, DC = vwg, DC = VWPKI, CN = VW-CA-PROC-09 + +-----BEGIN CERTIFICATE----- +MIIFdzCCA1+gAwIBAgIEAKYbnjANBgkqhkiG9w0BAQsFADBZMRMwEQYKCZImiZPy +LGQBGRYDY29tMRMwEQYKCZImiZPyLGQBGRYDdndnMRUwEwYKCZImiZPyLGQBGRYF +VldQS0kxFjAUBgNVBAMTDVZXLUNBLVBST0MtMDkwHhcNMjUwNTEzMDk1NTM0WhcN +MjcwNTEyMDk1NTMzWjA+MQswCQYDVQQGEwJDTjERMA8GA1UEChMIVlcgQ2hpbmEx +HDAaBgNVBAMTE3FhLm1kbWRzLm1hZXppYS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDJbCHfyLz03x35D9KaV/gaQNkE5PsV6irJU9Q9xJpDaKor ++iIgxpHavFaBD/XjtgFXlOHmFS2WZ/Fga7FE7anEPV4CTehvzK3XYIxUNjU3FTjG +89WlxPUInn79bfGShetyJD1x9ju/0LvQeYl31DVbssC1nqUbnwabFBChpx4LbRRV +26KWGaE6dOn9DFiDXDyVaxxBxTbpsMH7oa323yqvBkjI/N/jQL2ngIdIuLf/Z7Eh +vxtGE/8EjtfDVy2eBJTtWOOvyeJF0oCrgiU8JnCZ+cRKwp0LFaEdM9dZgWk+lyKV +jkjzG1KOfEgJhcKPo8xRgRwisx3mffLME33rAgVbAgMBAAGjggFgMIIBXDAdBgNV +HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEwYDVR0jBAwwCoAIRtIZUTdGOJUw +fgYIKwYBBQUHAQEEcjBwMDgGCCsGAQUFBzAChixodHRwOi8vYWlhLnBraS52d2dy +b3VwLmNvbS9WVy1DQS1QUk9DLTA5LmNlcjA0BggrBgEFBQcwAYYoaHR0cDovL29j +c3Audm9sa3N3YWdlbi5kZS9WVy1DQS1QUk9DLTA5LzAeBgNVHSAEFzAVMBMGESsG +AQQBmQqOWxQBAQICAwEAMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwudm9s +a3N3YWdlbi5kZS9WVy1DQS1QUk9DLTA5LkNSTDARBgNVHQ4ECgQIRjvHpRc3m8Uw +CwYDVR0PBAQDAgWgMB4GA1UdEQQXMBWCE3FhLm1kbWRzLm1hZXppYS5jb20wCQYD +VR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAHwkqbi1amSn4zbt4+iaw0ZsQHAvb +2tgVsXvrsVxCPNJ0GZ7Uz83sb0aP7Yj4YvzWOG1Ue/yNNXf/DlqPeKPgr8cwd4U8 +a95qQ2IjSJxLgxwbQt7t1iqC0OzJYt3HAC9Q7y2H6kFhp3/21F03zLSFRfxTUcNJ +brmfEddUC3b/v9qEk3uhHAI7Xik5iNjImqjTPWQtXoiVEwa7Cc7NNS863CUax7V7 +CmLCqZ3Blg5gRW54NRFo7h9X7x1CPM8UmzFzsa0Ga2e4OO6QDWzy71EwaN7Jcmcb +j12VTqQMBp9jR0N1GSVcL3leccXvHCqVDE8cV9kM9gESMnOnpa76ldBqIFIz3bAa +xGNloNz9zoq0aFRgw18532MTQLWuExzag16uo2/iNTB5rGvxt/nyiAa3hyfiSRmw +PLHPieH95+0vBFvZix1LcQYbGU6zOVbN8K9kOcgmWHltsBPXBA7fpm8owjgUe99O +w3wUIFsHtcF73IWTUTqy85UraiJpz7DCwsLP1AC42VuPzzCXCvRzAXAmlqRABkQs +oXZTRwtzJnbEAOtlQzq7AHhD1B1ZyTRHGkhHgWring9DIcYnolBSWDrghac40edB +pw0NYeZhhEnCQhODRjd0bMHeDkTlfPe4mdlTJcFG33emuCvvxv4106si0qfMJCia +XzWWGg7X0f6DYtI= +-----END CERTIFICATE----- + +subject=DC = com, DC = vwg, DC = VWPKI, CN = VW-CA-ROOT-05 + +issuer=DC = com, DC = vwg, DC = VWPKI, CN = VW-CA-ROOT-05 + +-----BEGIN CERTIFICATE----- +MIIFgDCCA2igAwIBAgIDET0sMA0GCSqGSIb3DQEBCwUAMFkxEzARBgoJkiaJk/Is +ZAEZFgNjb20xEzARBgoJkiaJk/IsZAEZFgN2d2cxFTATBgoJkiaJk/IsZAEZFgVW +V1BLSTEWMBQGA1UEAxMNVlctQ0EtUk9PVC0wNTAeFw0xMzA4MTMxMDAwMDBaFw0y +OTA4MTMxMDAwMDBaMFkxEzARBgoJkiaJk/IsZAEZFgNjb20xEzARBgoJkiaJk/Is +ZAEZFgN2d2cxFTATBgoJkiaJk/IsZAEZFgVWV1BLSTEWMBQGA1UEAxMNVlctQ0Et +Uk9PVC0wNTCCAiAwDQYJKoZIhvcNAQEBBQADggINADCCAggCggIBAJ8kcysP0wa6 +yB3obU7q0wZBhMUCJ0HzJ2yFVPm9+9uO4Dmtv6Kmk9j+Op4pZx/opclnx+bSTmXD +tr8f7C6XoZh1uvi0mLaXejs7ISl+etcB9IkgFeU+G4p3NyT7p4VjyrjtpK0jQ1U9 +a9STkFt7x++FcRAd3Dq16luOeJfsfZXKvy97WOdBQE2YKI5fw1r79z01NovQifDc +I+KCNeINxgGhVZpNWVmgR/VoD/OQGjk9CAPw/lIga/Lauzwr25SEK1tIEepOJ9K1 +iomQLfFzTxMOuz0WFeARZkE05SP+nnxl4C6aUWUGIcO7xjfAAKuU8AIXu158nG5O +Q9RYghMQx29jk4Wxm/YAwRrg/dkO2ROLTK58AG2NkMLGIAq7vgV8PMdleCbTzbaU +KCJ/Ke8n3hCsXChnqxZ+IjNXRpGv/HPzSYgXrzc4oEGt/sbfEHr+aF7VRnKUKe8c +RBM9Ahmd6yNn3ofLcyIICEUa7o949PtRrSJZcEt2eq5kw+xv8vSz3YIi1rWKZ9y4 +fHYf6c2T9ZY9QB6sr8QhI59iyMAs74tL004ckkuyZxEq7WD0kqcp9W/x28/IHLgf +ht30KUVtX3F7JioMIal1HqHg5YqK8wCX/rDe5L4vAK8yniA39Thx8bu4jHRaEdnm +Xeq9M9NZERBN8Mh4bmqKux4PczBS4+FZAgERo1MwUTAPBgNVHRMBAf8EBTADAQH/ +MBEGA1UdDgQKBAhC/VC3xdlYFDAeBgNVHSAEFzAVMBMGESsGAQQBmQqOWxQBAQIB +AQEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAjaHIBWv5vGOUoSni +C3LfTuqcMzuJLafQATJVp54h03yBVd/XDwf/RfGUujCFBxZ/yoIJCMx3U1VtJjWC +OmZH2xzFpMI0ypVJSMru/dZZrYYmS8DGlRa+I1ci4Ds4hR+SpsAzid09oz+vyBEF +WE5ILcLVnG1mdP/cdMd8G7f09QJFbib6Wsv6tv4OpPnFy0ULJr89N8dp9LCJy3Ta +n1BoyTpQ3CRa5Pl4e9RN1LvrEiJ+IcVRktbiLG/NzSJm4eikWH4kTonQWyt/ili5 +/12ojyaw+wXShXFn5RdzOVoNyZEx2P0x/SSpn/gxtsT1KvrsDFXSkpJAJcYr0NCB +KrR2FI1tly68VtM0BLvOXTGlQvIL7agjINHb9hLSd2XRCFP3krrMYblWQ+zm+I7w +i7ObenpeWwljlfiee0UWqBUaygfQN5s8meYB3EsLuFRq6lJRw641OFX9fiCJ6X+B +YiPFfp82GZNSdsCrlNqmK2mEckmKNV/MihIWVaCnB0HOyTkLrCzHiLkzX3Q/QFex +5yl1WeULz6P95PIczcX8YGM2jWgPrpMMl+ldxsfDeJWTgOyInsFY8yKZw574HVGO +UPwFzYIVkwy4ny+UJm9js8iynKro643mXty9vj5TdN1iK3ZA4f4/7kenuHtGBNur +WzUuf8H9dBW2DPtk5Jq/+QWtYMs= +-----END CERTIFICATE----- + +subject=DC = com, DC = vwg, DC = VWPKI, CN = VW-CA-PROC-09 + +issuer=DC = com, DC = vwg, DC = VWPKI, CN = VW-CA-ROOT-05 + +-----BEGIN CERTIFICATE----- +MIIGZDCCBEygAwIBAgIDW6NLMA0GCSqGSIb3DQEBCwUAMFkxEzARBgoJkiaJk/Is +ZAEZFgNjb20xEzARBgoJkiaJk/IsZAEZFgN2d2cxFTATBgoJkiaJk/IsZAEZFgVW +V1BLSTEWMBQGA1UEAxMNVlctQ0EtUk9PVC0wNTAeFw0yMTA3MTMxMDAwMDBaFw0y +OTA4MTMxMDAwMDBaMFkxEzARBgoJkiaJk/IsZAEZFgNjb20xEzARBgoJkiaJk/Is +ZAEZFgN2d2cxFTATBgoJkiaJk/IsZAEZFgVWV1BLSTEWMBQGA1UEAxMNVlctQ0Et +UFJPQy0wOTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM0kqWGmgxe3 +NrbKWvL8/DIA1JcHD5BddqDbZaPbUwIYKBDfCUPX6DXJqtzmQ6257dmj8qyMOQwa +7qNwG7wEt0Jiytqjj7yRbNhd4l/hlGjMK/THnlc+jV6Wrrx8onNFj/Ks49N2VzeN +heJ8WfQmXbBxNmzDgs3my7V9KnYsDr2e8EA4KxQOJwD4h0Zutvf5yiwOVhr2VtzB +l192CJtpLwyOBIerHmFqbXy5fvtj5ucRflb4BAf1/Aqa17ntDA+gBYwQ6TxJ+GTk +MHVK6oCxXJxuFtaWvpKYiiTQA+oMf0zOaYyDCQRPD3Hdv7BZ5x+E7stU9NAVrwDh +PiDxS9xxMNbPxqeASmmDf4+oNPTON05R2V05JMsUufFeoRomAbYO133SUTJWmyde +7DMegVZpLAx01QgBZfNQ1okk2z8pEPA9nPcuMvB/V7u2PeXNkQSjFCQG+yTlQRqI +DY1vaySU8QWUbL92upCoRh6NafkWuegoAyRLtpgRmpVRcaZGOKsVsqsy4Oruoc6C +yiV4HKBWxaetwYeJvmuVtTs1DZZq/LDryhfIiog0/iglnsJUqsJgnpddxULlDfpd +KcSLLB593KwZUbGI3CSYaBX3kDi+OcVgj1ZbOfDBwzdAB/0Ps7afEfGXPVUXcpuP +E+ufwJLz2vX0uz8p3gKSKeWdUDOYwPvXAgMBAAGjggEzMIIBLzASBgNVHRMBAf8E +CDAGAQH/AgEAMBEGA1UdDgQKBAhG0hlRN0Y4lTAmBgNVHSAEHzAdMAYGBFUdIAAw +EwYRKwYBBAGZCo5bFAEBAgEBAQAwEwYDVR0jBAwwCoAIQv1Qt8XZWBQwNQYIKwYB +BQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC52b2xrc3dhZ2VuLmRl +MAsGA1UdDwQEAwIBBjCBhAYDVR0fBH0wezAwoC6gLIYqaHR0cDovL2NybC52b2xr +c3dhZ2VuLmRlL1ZXLUNBLVJPT1QtMDUuQ1JMMEegRaBDhkFsZGFwOi8vbGRhcC52 +b2xrc3dhZ2VuLmRlL2NuPVZXLUNBLVJPT1QtMDUsZGM9dndQS0ksZGM9dndnLGRj +PWNvbTANBgkqhkiG9w0BAQsFAAOCAgEAAib1vxHeT2IeAhU318gSzRmieCmIhJN3 +kQB0s64mgdtkE9RahnaWfSjceLwEPgzjLY3byubV9tq+p/Ow3eH/DgHoV4QlTUgE +7G8g2VLO6tOno96i0QZuzmnNvcKawRzthUEp5xKsXa2MJtdwbiCjaZ6VDAuycJoj +oeBiZWW4VAhjhZR9NEkWCQiU4wM6oDnVsWS2yHxDO2D0QAwkD49AoqYCVThqfGZ7 +uAVJJAb3TxzIOtB3UVZuNLL8jVzIbgbmxpN63OUGnlWdw/f9IkH2P+fnol0mcMeE +gyPt1cpTn8T3WsrIBUqN1qSdD71lksn4EiPSCOc+y5d6jegqyxzCX7F625O20Kut +4uzPFCb1q1mhUz2qIunXNGSnMu36CEjFmwFc2CG9KkuzFte7YNw9143tMOAtgJZk +PTxdGnvCxcuExBvk/MErTz/TOJVQglzN73qIiAxm/DwKpy9SYhDYaxGIF8Kl5IeB +G/wkvhbWC4aJmIwtv1G/Z1I8PEKoZ56dMf2iFcdfV1i2W5iiRFdY3GjP7kf1nayH +IL0VD86r5yTxfGxhEt+Z1E9fpwmMoXv22AdyYCIZie38iykN0AknAUkcKpohCgqC +LcvdJpLZLkNkyaK+22W1nykN+HHrw2JXB7b/tGlFvdMAaTqpzzWEGR4kdk6tPRlj +8rX3EW8GHlo= +-----END CERTIFICATE----- + diff --git a/src/main/resources/read.txt b/src/main/resources/read.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/sql/ddl_adapter_2025425.sql b/src/main/resources/sql/ddl_adapter_2025425.sql new file mode 100644 index 0000000..013f77c --- /dev/null +++ b/src/main/resources/sql/ddl_adapter_2025425.sql @@ -0,0 +1,22 @@ +-- public.dic_vehicle_attr_adapter definition + +-- Drop table + +-- DROP TABLE public.dic_vehicle_attr_adapter; + +CREATE TABLE public.dic_vehicle_attr_adapter ( + id bpchar(36) NOT NULL, + create_by varchar(255) NULL, + creation_date timestamptz NULL, + last_modified_by varchar(255) NULL, + last_modified_date timestamptz NULL, + attr_name varchar(255) NULL, + adapter_mapping varchar(255) NULL, + adapter_key varchar(255) NULL, + adapter_value varchar(255) NULL, + CONSTRAINT dic_vehicle_attr_adapter_pkey PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX dic_vehicle_attr_adapter_adapter_mapping_idx ON dic_vehicle_attr_adapter (adapter_mapping); + +ALTER TABLE public.data_collection_config ALTER COLUMN event_list TYPE text USING event_list::text; \ No newline at end of file diff --git a/src/main/resources/sql/dic_resource_202501211554.sql b/src/main/resources/sql/dic_resource_202501211554.sql new file mode 100644 index 0000000..8c3ecf4 --- /dev/null +++ b/src/main/resources/sql/dic_resource_202501211554.sql @@ -0,0 +1,6 @@ +INSERT INTO public.dic_resource (id,create_by,creation_date,last_modified_by,last_modified_date,res_name,res_url) VALUES + ('59bd3b60-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:52:34+08','SYS','2023-03-23 02:52:34+08','Ticket Management','Ticket Management'), + ('59bd3c46-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:52:34+08','SYS','2023-03-23 02:52:34+08','Configuration Management','Configuration Management'), + ('59bd3ca3-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:52:34+08','SYS','2023-03-23 02:52:34+08','Permission Management','Permission Management'), + ('59bd38ef-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:52:34+08','SYS','2023-03-23 02:52:34+08','Group Management','Vehicle Management'), + ('59bd3cf1-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:52:34+08','SYS','2023-03-23 02:52:34+08','Data Source Management','Data Source Management'); diff --git a/src/main/resources/sql/dic_vehicle_attr_202501211606.sql b/src/main/resources/sql/dic_vehicle_attr_202501211606.sql new file mode 100644 index 0000000..9934594 --- /dev/null +++ b/src/main/resources/sql/dic_vehicle_attr_202501211606.sql @@ -0,0 +1,13 @@ +INSERT INTO public.dic_vehicle_attr (id,create_by,creation_date,last_modified_by,last_modified_date,attr_name,mapping_name,remark,status) VALUES + ('18f4021e-5fa0-467b-91af-4c3897bad0e4','SYS','2024-10-15 13:20:48.159+08','SYS','2024-10-21 10:33:17.448+08','ABC','OP_BBC','This attribute can not be found in DT','ENABLE'), + ('cf652dd7-cbf2-4327-82a2-7174154dd9bd','SYS','2024-03-14 13:03:14.398+08','SYS','2024-10-21 11:36:46.894+08','model_family_n.a','Model Family','This attribute can not be found in DT','ENABLE'), + ('f65073da-b86e-4398-8439-d1a73c8d6392','SYS','2024-04-11 17:45:37.247+08','SYS','2024-10-21 11:37:15.495+08','2','2','This attribute can not be found in DT','DISABLE'), + ('e65ff59b-6f07-4164-9812-9e5b4c731015','SYS','2024-03-14 13:03:14.396+08','SYS','2024-03-14 13:03:14.396+08','ads_version','ADS Version','','ENABLE'), + ('f5e8aef7-958f-461b-876e-dae8cc3f4a02','SYS','2024-03-14 13:03:14.397+08','SYS','2024-03-14 13:03:14.397+08','brand_code','Brand Code','','ENABLE'), + ('52590b3f-3493-4939-96de-87524b0d26b9','SYS','2024-03-14 13:03:14.397+08','SYS','2024-03-14 13:03:14.397+08','vehicleOrgLevel2','Brand Name','','ENABLE'), + ('6420cc9b-6c03-452a-b860-f84b1440af11','SYS','2024-03-14 13:03:14.398+08','SYS','2024-03-14 13:03:14.398+08','model/model_codes','Model Code','','ENABLE'), + ('37c47b61-07e2-48f2-a845-394ebf7eda3a','SYS','2024-03-14 13:03:14.398+08','SYS','2024-03-14 13:03:14.398+08','model/model_name','Model Name','','ENABLE'), + ('0c997f73-1b9b-4b09-80c5-5211c437c0b7','SYS','2024-03-14 13:03:14.399+08','SYS','2024-03-14 13:03:14.399+08','model/model_year','Model Year','','ENABLE'), + ('7fc7c909-bcc7-4f6e-8b1d-942562559b44','SYS','2024-03-14 13:03:14.399+08','SYS','2024-03-14 13:03:14.399+08','platform_name_n.a','Platform Name','This attribute can not be found in DT','DISABLE'); +INSERT INTO public.dic_vehicle_attr (id,create_by,creation_date,last_modified_by,last_modified_date,attr_name,mapping_name,remark,status) VALUES + ('cdf240a4-7c4e-48d5-abf2-e337a0f5bf28','SYS','2024-03-14 13:03:14.399+08','SYS','2024-03-14 13:03:14.399+08','platform_variant_n.a','Platform Variant','This attribute can not be found in DT','DISABLE'); diff --git a/src/main/resources/sql/role_info_202501211555.sql b/src/main/resources/sql/role_info_202501211555.sql new file mode 100644 index 0000000..81025b0 --- /dev/null +++ b/src/main/resources/sql/role_info_202501211555.sql @@ -0,0 +1,3 @@ +INSERT INTO public.role_info (id,create_by,creation_date,last_modified_by,last_modified_date,role_name,inner_role) VALUES + ('fdc5cea0-cea1-11ed-b60e-be152da4ad78','SYS','2023-03-30 02:27:59+08','SYS','2024-02-26 18:10:56.11+08','CLOUDIDP_EHR_USER','INNER_GROUP,INNER_TICKET,INNER_CONFIGURATION,INNER_DATASOURCE'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','SYS','2023-03-23 02:00:27+08','SYS','2023-10-13 14:51:46.261+08','CLOUDIDP_EHR_ADMIN','INNER_GROUP,INNER_TICKET,INNER_CONFIGURATION,INNER_PERMISSION,INNER_DATASOURCE'); diff --git a/src/main/resources/sql/role_info_dic_resources_202501211556.sql b/src/main/resources/sql/role_info_dic_resources_202501211556.sql new file mode 100644 index 0000000..cce8739 --- /dev/null +++ b/src/main/resources/sql/role_info_dic_resources_202501211556.sql @@ -0,0 +1,10 @@ +INSERT INTO public.role_info_dic_resources (role_info_id,dic_resources_id) VALUES + ('fdc5cea0-cea1-11ed-b60e-be152da4ad78','59bd38ef-c925-11ed-b60e-be152da4ad78'), + ('fdc5cea0-cea1-11ed-b60e-be152da4ad78','59bd3c46-c925-11ed-b60e-be152da4ad78'), + ('fdc5cea0-cea1-11ed-b60e-be152da4ad78','59bd3cf1-c925-11ed-b60e-be152da4ad78'), + ('fdc5cea0-cea1-11ed-b60e-be152da4ad78','59bd3b60-c925-11ed-b60e-be152da4ad78'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','59bd3c46-c925-11ed-b60e-be152da4ad78'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','59bd3ca3-c925-11ed-b60e-be152da4ad78'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','59bd3cf1-c925-11ed-b60e-be152da4ad78'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','59bd3b60-c925-11ed-b60e-be152da4ad78'), + ('559ca2d4-c925-11ed-b60e-be152da4ad78','59bd38ef-c925-11ed-b60e-be152da4ad78'); diff --git a/src/test/java/com/volkswagen/mdmds/MdmdsProdBsApplicationTests.java b/src/test/java/com/volkswagen/mdmds/MdmdsProdBsApplicationTests.java new file mode 100644 index 0000000..545f22c --- /dev/null +++ b/src/test/java/com/volkswagen/mdmds/MdmdsProdBsApplicationTests.java @@ -0,0 +1,56 @@ +package com.volkswagen.mdmds; + +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.service.AttributeService; +import jakarta.validation.constraints.AssertTrue; +import org.junit.jupiter.api.Test; +import org.modelmapper.internal.util.Assert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.AssertionErrors; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@SpringBootTest +class MdmdsProdBsApplicationTests { + + @Autowired + private AttributeService attributeService; + + @Test + void contextLoads() { + AssertionErrors.assertTrue("", true); + //初始化数据库 + //车辆属性表,带映射关系 + List attrs = Arrays.asList("brand_name", + "platform", + "platform_class", + "platform_variant", + "model_code", + "model_name", + "model_status", + "model_group", + "model_year", + "model_family", + "vehicle_project", + "vehicle_type", + "drive_type", + "vehicle_segment", + "body_style", + "sales_name", + "brand_code", + "region_of_market", + "country_of_market", + "equipment_options", + "ecus", + "engine", + "life_data"); + + + } + +} diff --git a/src/test/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepositoryTest.java b/src/test/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepositoryTest.java new file mode 100644 index 0000000..9dd9dca --- /dev/null +++ b/src/test/java/com/volkswagen/mdmds/repos/DicVehicleAttrRepositoryTest.java @@ -0,0 +1,39 @@ +package com.volkswagen.mdmds.repos; + +import com.volkswagen.mdmds.model.dto.AttributeDTO; +import com.volkswagen.mdmds.model.entity.DicVehicleAttr; +import com.volkswagen.mdmds.model.entity.ItemStatus; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.AssertionErrors; + +import java.util.List; + +/** + * @author Shuo Ding + * @since 2023/2/20 + */ +@SpringBootTest +class DicVehicleAttrRepositoryTest { + + @Autowired + private DicVehicleAttrRepository attrRepository; + + @Test + void testAddAttr(){ + DicVehicleAttr dicVehicleAttr = new DicVehicleAttr(); + AssertionErrors.assertTrue("", true); + dicVehicleAttr.setAttrName("ABC"); + dicVehicleAttr.setMappingName("OP_BBC"); + dicVehicleAttr.setStatus(ItemStatus.ENABLE); + attrRepository.save(dicVehicleAttr); + } + + @Test + void SpecifiQuery(){ + List custom = attrRepository.findBy(); + AssertionErrors.assertTrue("", true); + System.out.println(custom); + } +} \ No newline at end of file diff --git a/src/test/java/com/volkswagen/mdmds/service/impl/DTServiceImplTest.java b/src/test/java/com/volkswagen/mdmds/service/impl/DTServiceImplTest.java new file mode 100644 index 0000000..05b8590 --- /dev/null +++ b/src/test/java/com/volkswagen/mdmds/service/impl/DTServiceImplTest.java @@ -0,0 +1,140 @@ +package com.volkswagen.mdmds.service.impl; + +import com.volkswagen.mdmds.service.LinkDTService; +import com.volkswagen.mdmds.utils.MyHttpClient; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.util.AssertionErrors; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; + +/** + * @author Shuo Ding + * @since 2023/3/22 + */ +@SpringBootTest +@ActiveProfiles("dev") +class DTServiceImplTest { + + @Autowired + private LinkDTService digitalTwinService; + + @Test + void test() { + AssertionErrors.assertTrue("", true); + for(int k = 0; k < 1; k++) { + Long sTime = System.currentTimeMillis(); + List> initThreads = new ArrayList<>(); + for(int index = 0; index < 50; index++) { + int finalIndex = index; + Callable callable = () -> { + String indexStr = assemble(finalIndex); + System.out.println(Thread.currentThread().getName() + "======" + indexStr); + return true; + }; + initThreads.add(callable); + } +// TestThreadPoolUtil.addThread(initThreads); + System.out.println("总共耗时:" + String.valueOf(System.currentTimeMillis() - sTime)); + } + System.out.println("=================================="); + } + + private String assemble(int index) { +// try { +// Thread.sleep(1200); +//// System.out.println(index + "=====" + Thread.currentThread().getState()); +// } catch (InterruptedException e) { +// System.out.println(index + "=====" + Thread.currentThread().getState()); +// e.printStackTrace(); +// } + return "=====" + index; + } + + @Test + void testSSL() { + try { + HttpClient.Builder httpClientBuilder = MyHttpClient.getClient(); + HttpClient httpClient = httpClientBuilder.build(); + AssertionErrors.assertTrue("", true); + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("https") + .host("paas-apr-china.apr.digitaltwin.vwcloud.cn") + .path("/digitaltwin-api/ConstructionState/listByQuery") + .build(); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uriComponents.toUri()) + .header("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Il9DSkFPdHlzWVZtNXhjMVlvSzBvUTdxeUJDUSIsImtpZCI6Il9DSkFPdHlzWVZtNXhjMVlvSzBvUTdxeUJDUSJ9.eyJhdWQiOiI4ODY0MmIyNy0wMjgyLTQ0NDgtYTYyYy1mZWI3MjU3MjdlNjIiLCJpc3MiOiJodHRwczovL3N0cy5jaGluYWNsb3VkYXBpLmNuL2ExMmE4MmZmLWViNjgtNGQ2ZC1iM2M3LWM0ZmIyZDIyMjBlNS8iLCJpYXQiOjE2ODE0NDk3NDQsIm5iZiI6MTY4MTQ0OTc0NCwiZXhwIjoxNjgxNDUzNjQ0LCJhaW8iOiI0MkpnWURDK0U5dThQSzlsRy9zLzYrTjNDaDVXQVFBPSIsImFwcGlkIjoiMzVlMDU3MTktNTJlNi00YTU2LWE4MzUtZjVlMjllYTY0ZDVkIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMuY2hpbmFjbG91ZGFwaS5jbi9hMTJhODJmZi1lYjY4LTRkNmQtYjNjNy1jNGZiMmQyMjIwZTUvIiwiaWR0eXAiOiJhcHAiLCJvaWQiOiI3ZjYxYTI5OC1mYTk4LTQ1NDUtYWRkYy1iMzczZDgzNDFkOGEiLCJyaCI6IjAuQVFJQV80SXFvV2pyYlUyeng4VDdMU0lnNVNjclpJaUNBa2hFcGl6LXR5VnlmbUlDQUFBLiIsInJvbGVzIjpbIlN0YXRlLlJlYWQiXSwic2lkIjoiNmMzZWU5NzktZTJkNy00ODdhLWI2YjktYjk0NTFhNTZlOGU1Iiwic3ViIjoiN2Y2MWEyOTgtZmE5OC00NTQ1LWFkZGMtYjM3M2Q4MzQxZDhhIiwidGVuYW50X2N0cnkiOiJDTiIsInRlbmFudF9yZWdpb25fc2NvcGUiOiJBUyIsInRpZCI6ImExMmE4MmZmLWViNjgtNGQ2ZC1iM2M3LWM0ZmIyZDIyMjBlNSIsInV0aSI6IlZaZ1ZNMHMxYjAyNFlsaFExMDRGQUEiLCJ2ZXIiOiIxLjAifQ.zJBEj6a9p9oHTQhQWpcRmVbYNSRXaS5CgKDh_77-mimysFrcEhkFO4gAqVEFkTVfDvGN81LwrrLg_FDcbRAS51n8TZ30xGrBIB4HJ8B8BJGYt8URYwTahXmrxnhfJT79NZAzS2mNzw7a4rxGU9ByYtn6mLJdFOE7LLzDDU65jry7gsI1hGs0q9A1G_HtAh5jAHu4iIk1p097TcYYU4gK0lh9-DafUuF-IkWv-ueBAjzIiSEKDCvgK-MPiFfqTdI-JPqf2PEJrDK0p2eLrn0qzSgwAUzkY_gwFeMqK1dRzOom7clrzQ3IAYg4rty-Q5kRcRNUx-Nsc5QjFYWWI-vLpA") + .timeout(Duration.ofMillis(5000)); + requestBuilder.header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString("{\"and\":[{\"ads_version\":\"1.1.1\"}]}")); + HttpRequest httpRequest = requestBuilder.build(); + + HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + System.out.println("=========================" + response.body().toString()); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + @Test + void getAllEnumForAttribute() throws IOException, InterruptedException, ExecutionException, NoSuchAlgorithmException, KeyManagementException { +// String params = "brand_name"; + AssertionErrors.assertTrue("", true); + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("key", "brand_name"); + Object vehicleIds = digitalTwinService.getAllEnumForAttribute(params); + System.out.println(vehicleIds.toString()); +// Assert.notNull(allAttributes); + } + + @Test + void getVehicleIdByCondition() throws IOException, InterruptedException, ExecutionException, NoSuchAlgorithmException, KeyManagementException { + String params = "{\"or\":[{\"color\":\"blue\"},{\"brand_name\":\"Audi\"},{\"country_composition\":\"X0A\"}]}"; + Object vehicleIds = digitalTwinService.getVehicleIdByCondition(params); + AssertionErrors.assertTrue("", true); + System.out.println(vehicleIds.toString()); +// Assert.notNull(allAttributes); + } + + @Test + void getAllAttributes() throws IOException, InterruptedException, ExecutionException, NoSuchAlgorithmException, KeyManagementException { + Object allAttributes = digitalTwinService.getAllAttributes(); + AssertionErrors.assertTrue("", true); + System.out.println(allAttributes.toString()); +// Assert.notNull(allAttributes); + } + + @Test + void testGetVehicleInfo() throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { + List vidList = Arrays.asList("myvehicle", + "e2d92109-ff16-4acb-b365-84f8c7d9f098", + "cf2cbb8f323d423e91cd99b9a6578dfe", + "57526e2e94f54505aba199c3ad5d7ada", + "de47e2cfa33d46b79f1c3b78202d2338", + "9c2865ab252c424fbf679bbbe1b4053d", + "a9016633b92549a0b44236881e97b0db", + "817ea67d292748e08c0a5d267619a042"); + AssertionErrors.assertTrue("", true); + Object vehicleInfo = digitalTwinService.getVehicleInfo(vidList); + System.out.println(vehicleInfo); + } + +} \ No newline at end of file diff --git a/src/test/java/com/volkswagen/mdmds/service/impl/VWACServiceImplTest.java b/src/test/java/com/volkswagen/mdmds/service/impl/VWACServiceImplTest.java new file mode 100644 index 0000000..0347458 --- /dev/null +++ b/src/test/java/com/volkswagen/mdmds/service/impl/VWACServiceImplTest.java @@ -0,0 +1,33 @@ +package com.volkswagen.mdmds.service.impl; + +import com.volkswagen.mdmds.service.LinkVWACService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.util.AssertionErrors; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +@SpringBootTest +@ActiveProfiles("dev") +class VWACServiceImplTest { + + @Autowired + private LinkVWACService linkVWACService; + + @Test + void getVINByVID() throws NoSuchAlgorithmException, IOException, InterruptedException, KeyManagementException { + AssertionErrors.assertTrue("", true); + linkVWACService.getVINByVID("97c7b558b17c4d2f99a3aadc847f9b71"); + } + + @Test + void getVIDByVIN() throws NoSuchAlgorithmException, IOException, InterruptedException, KeyManagementException { + AssertionErrors.assertTrue("", true); + linkVWACService.getVIDByVIN("BAUNEEGFZ22091314"); + } + +}