From 10ec801de3e570072147308a0b1cb1e87295d188 Mon Sep 17 00:00:00 2001 From: Hoshi <1196756653@qq.com> Date: Tue, 20 Aug 2024 17:56:42 +0800 Subject: [PATCH] Initial commit all --- bocloud.ams.booter/.gitignore | 10 + bocloud.ams.booter/pom.xml | 157 ++ .../com/bocloud/ams/booter/Application.java | 24 + .../booter/config/RabbitMQConfiguration.java | 145 + .../booter/config/SwaggerConfiguration.java | 20 + .../config/WebInterceptorConfiguration.java | 62 + .../AutoRelationRuleController.java | 112 + .../audit/OperationalAuditController.java | 57 + .../CollectionHistoryController.java | 81 + .../CollectionHistoryItemController.java | 37 + .../collection/CollectionTaskController.java | 161 ++ .../CollectionTaskInstanceController.java | 57 + .../CollectionTemplateController.java | 113 + .../config/CmdbConfigController.java | 75 + .../instance/InstanceAuthoryController.java | 89 + .../instance/InstanceController.java | 226 ++ .../instance/InstanceHistoryController.java | 36 + .../instance/InstanceRelationController.java | 88 + ...stanceRelationHistoryRecordController.java | 80 + .../controller/module/ModuleController.java | 192 ++ .../module/ModuleGroupController.java | 159 ++ .../module/ModuleRelationController.java | 192 ++ .../controller/module/PropertyController.java | 36 + .../module/PropertyPoolController.java | 135 + .../module/RegularExpressionController.java | 37 + .../module/RelationCategoryController.java | 132 + .../controller/module/RelationController.java | 105 + .../module/TopologyConfigController.java | 237 ++ .../booter/listener/TaskResultListener.java | 93 + .../CollectionTaskInstanceBakScheduler.java | 373 +++ .../ModuleInstanceRelationScheduler.java | 50 + .../OperationalAuditBakScheduler.java | 231 ++ .../syslog/SysLogAppenderTcpAndUdp.java | 15 + .../booter/syslog/SysLogLevelConvertor.java | 22 + .../syslog/SyslogOutputStreamTcpAndUdp.java | 70 + .../src/main/resources/application.yml | 110 + .../src/main/resources/banner.txt | 8 + .../src/main/resources/logback-spring.xml | 73 + bocloud.ams.entity/.gitignore | 10 + bocloud.ams.entity/pom.xml | 18 + .../bocloud/ams/annotation/ColumnType.java | 14 + .../java/com/bocloud/ams/entity/Role.java | 16 + .../java/com/bocloud/ams/entity/TableLog.java | 30 + .../entity/association/AutoRelationRule.java | 46 + .../association/AutoRelationRuleItem.java | 71 + .../AutoRelationRuleItemValue.java | 79 + .../ams/entity/audit/OperationalAudit.java | 58 + .../ams/entity/audit/OperationalAuditBak.java | 110 + .../collection/CollectionComponent.java | 48 + .../entity/collection/CollectionHistory.java | 58 + .../collection/CollectionHistoryBak.java | 53 + .../collection/CollectionHistoryItem.java | 41 + .../collection/CollectionHistoryItemBak.java | 34 + .../ams/entity/collection/CollectionTask.java | 47 + .../collection/CollectionTaskInstance.java | 142 + .../collection/CollectionTaskInstanceBak.java | 160 ++ .../entity/collection/CollectionTemplate.java | 37 + .../bocloud/ams/entity/config/CmdbConfig.java | 101 + .../bocloud/ams/entity/enums/ApplyStatus.java | 36 + .../ams/entity/enums/CollectionEnum.java | 220 ++ .../ams/entity/enums/InstanceEnum.java | 66 + .../entity/enums/OperationalAuditType.java | 49 + .../ams/entity/enums/PropertyType.java | 57 + .../com/bocloud/ams/entity/enums/Status.java | 126 + .../bocloud/ams/entity/instance/Instance.java | 35 + .../entity/instance/InstanceAuthority.java | 64 + .../ams/entity/instance/InstanceHistory.java | 62 + .../ams/entity/instance/InstanceRelation.java | 80 + .../InstanceRelationHistoryRecord.java | 92 + .../ams/entity/instance/InstanceValue.java | 40 + .../entity/model/CollectionHistoryModel.java | 11 + .../model/ColumnAndSearchItemModel.java | 24 + .../bocloud/ams/entity/model/ColumnModel.java | 32 + .../ams/entity/model/InstanceBean.java | 22 + .../ams/entity/model/InstanceLink.java | 45 + .../ams/entity/model/InstanceModel.java | 29 + .../ams/entity/model/InstanceNodeModel.java | 35 + .../InstanceRelationHistoryAlterModel.java | 31 + ...InstanceRelationHistoryPreflightModel.java | 27 + .../entity/model/InstanceRelationModel.java | 37 + .../ams/entity/model/InstanceTopo.java | 18 + .../bocloud/ams/entity/model/ModuleLink.java | 34 + .../bocloud/ams/entity/model/ModuleTopo.java | 30 + .../ams/entity/model/NotifyMessage.java | 128 + .../ams/entity/model/OperateParam.java | 15 + .../bocloud/ams/entity/model/PathModel.java | 25 + .../ams/entity/model/PropertyModel.java | 37 + .../model/RequestInstanceTopologyModel.java | 20 + .../model/ResponseInstanceTopologyModel.java | 20 + .../com/bocloud/ams/entity/model/Role.java | 33 + .../ams/entity/model/SearchConfigModel.java | 49 + .../ams/entity/model/StartModeParams.java | 17 + .../bocloud/ams/entity/model/TaskBean.java | 19 + .../bocloud/ams/entity/model/TaskGraph.java | 35 + .../ams/entity/model/TaskInstanceBean.java | 32 + .../bocloud/ams/entity/model/TaskNode.java | 17 + .../ams/entity/model/TaskTransferParams.java | 24 + .../bocloud/ams/entity/module/CiModule.java | 40 + .../ams/entity/module/ModuleGroup.java | 42 + .../ams/entity/module/ModuleRelation.java | 85 + .../bocloud/ams/entity/module/Property.java | 224 ++ .../ams/entity/module/PropertyGroup.java | 34 + .../ams/entity/module/PropertyItem.java | 72 + .../ams/entity/module/PropertyPool.java | 180 ++ .../ams/entity/module/PropertyPoolItem.java | 91 + .../ams/entity/module/RegularExpression.java | 34 + .../bocloud/ams/entity/module/Relation.java | 58 + .../ams/entity/module/RelationCategory.java | 43 + .../ams/entity/module/TopologyConfig.java | 120 + bocloud.ams.repository/.gitignore | 10 + bocloud.ams.repository/pom.xml | 18 + .../ams/repository/TableLogRepository.java | 28 + .../AutoRelationRuleItemRepository.java | 50 + .../AutoRelationRuleItemValueRepository.java | 45 + .../AutoRelationRuleRepository.java | 107 + .../audit/OperationalAuditBakRepository.java | 143 + .../audit/OperationalAuditRepository.java | 76 + .../CollectionComponentRepository.java | 98 + .../CollectionHistoryBakRepository.java | 77 + .../CollectionHistoryItemBakRepository.java | 77 + .../CollectionHistoryItemRepository.java | 69 + .../CollectionHistoryRepository.java | 92 + .../CollectionTaskInstanceBakRepository.java | 79 + .../CollectionTaskInstanceRepository.java | 122 + .../collection/CollectionTaskRepository.java | 112 + .../CollectionTemplateRepository.java | 76 + .../config/CmdbConfigRepository.java | 62 + .../instance/InstanceAuthorityRepository.java | 157 ++ .../instance/InstanceHistoryRepository.java | 62 + ...stanceRelationHistoryRecordRepository.java | 62 + .../instance/InstanceRelationRepository.java | 298 +++ .../instance/InstanceRepository.java | 199 ++ .../instance/InstanceValueRepository.java | 176 ++ .../module/ModuleGroupRepository.java | 73 + .../module/ModuleRelationRepository.java | 137 + .../repository/module/ModuleRepository.java | 117 + .../module/PropertyGroupRepository.java | 41 + .../module/PropertyItemRepository.java | 53 + .../module/PropertyPoolItemRepository.java | 61 + .../module/PropertyPoolRepository.java | 72 + .../repository/module/PropertyRepository.java | 113 + .../module/RegularExpressionRepository.java | 39 + .../module/RelationCategoryRepository.java | 79 + .../repository/module/RelationRepository.java | 82 + .../module/TopologyConfigRepository.java | 82 + .../ams/repository/utils/CmdbUtils.java | 495 ++++ bocloud.ams.service/.gitignore | 10 + bocloud.ams.service/pom.xml | 58 + .../AutoRelationRuleItemService.java | 13 + .../association/AutoRelationRuleService.java | 30 + .../impl/AutoRelationRuleItemServiceImpl.java | 39 + .../impl/AutoRelationRuleServiceImpl.java | 234 ++ .../audit/OperationalAuditService.java | 41 + .../impl/OperationalAuditServiceImpl.java | 196 ++ .../CollectionHistoryItemService.java | 21 + .../collection/CollectionHistoryService.java | 39 + .../CollectionTaskInstanceService.java | 29 + .../collection/CollectionTaskService.java | 61 + .../collection/CollectionTemplateService.java | 28 + .../CollectionHistoryItemServiceImpl.java | 68 + .../impl/CollectionHistoryServiceImpl.java | 529 ++++ .../CollectionTaskInstanceServiceImpl.java | 351 +++ .../impl/CollectionTaskServiceImpl.java | 776 ++++++ .../impl/CollectionTemplateServiceImpl.java | 255 ++ .../ams/service/config/CmdbConfigService.java | 36 + .../config/impl/CmdbConfigServiceImpl.java | 150 ++ .../ams/service/core/CmdbConfigCache.java | 56 + .../instance/InstanceAuthorityService.java | 31 + .../instance/InstanceAutoRelationService.java | 35 + .../instance/InstanceHistoryService.java | 23 + .../InstanceRelationHistoryRecordService.java | 54 + .../instance/InstanceRelationService.java | 21 + .../ams/service/instance/InstanceService.java | 57 + .../instance/InstanceValueService.java | 18 + .../impl/InstanceAuthorityServiceImpl.java | 246 ++ .../impl/InstanceAutoRelationServiceImpl.java | 209 ++ .../impl/InstanceHistoryServiceImpl.java | 87 + ...tanceRelationHistoryRecordServiceImpl.java | 1148 ++++++++ .../impl/InstanceRelationServiceImpl.java | 363 +++ .../instance/impl/InstanceServiceImpl.java | 2369 +++++++++++++++++ .../impl/InstanceValueServiceImpl.java | 59 + .../service/internal/AmsInternalService.java | 58 + .../service/internal/SmsInternalService.java | 62 + .../service/module/ModuleGroupService.java | 35 + .../service/module/ModuleRelationService.java | 76 + .../ams/service/module/ModuleService.java | 38 + .../service/module/PropertyPoolService.java | 47 + .../ams/service/module/PropertyService.java | 18 + .../module/RegularExpressionService.java | 23 + .../module/RelationCategoryService.java | 64 + .../ams/service/module/RelationService.java | 40 + .../service/module/TopologyConfigService.java | 149 ++ .../module/impl/ModuleGroupServiceImpl.java | 573 ++++ .../impl/ModuleRelationServiceImpl.java | 592 ++++ .../module/impl/ModuleServiceImpl.java | 773 ++++++ .../module/impl/PropertyPoolServiceImpl.java | 424 +++ .../module/impl/PropertyServiceImpl.java | 155 ++ .../impl/RegularExpressionServiceImpl.java | 48 + .../impl/RelationCategoryServiceImpl.java | 245 ++ .../module/impl/RelationServiceImpl.java | 145 + .../impl/TopologyConfigServiceImpl.java | 1427 ++++++++++ .../service/task/InstanceRelationTask.java | 1126 ++++++++ .../task/ModuleInstanceRelationTask.java | 649 +++++ .../AutoModuleInstanceRelationUtils.java | 410 +++ .../ams/service/utils/BoStringUtils.java | 336 +++ .../utils/CollectionHistoryHelper.java | 542 ++++ .../ams/service/utils/EventPublisher.java | 42 + .../ams/service/utils/ExcelFactory.java | 210 ++ .../ams/service/utils/ExcelHelper.java | 605 +++++ .../service/utils/GraphAlgorithmUtils.java | 111 + .../service/utils/InstanceExcelHelper.java | 646 +++++ .../service/utils/InstanceHistoryHelper.java | 170 ++ .../ams/service/utils/JsonCompareUtil.java | 248 ++ .../ams/service/utils/ModuleConstant.java | 28 + .../ams/service/utils/PropertyConstant.java | 107 + .../utils/RelationHistoryConstant.java | 74 + .../ams/service/utils/RepositoryHandler.java | 123 + .../ams/service/utils/StreamUtils.java | 24 + .../ams/service/utils/paginationUtil.java | 51 + bocloud.ams.task/.gitignore | 10 + bocloud.ams.task/pom.xml | 28 + .../bocloud/ams/task/annotation/Module.java | 16 + .../bocloud/ams/task/annotation/Worker.java | 13 + .../task/exception/NodeFormatException.java | 30 + .../ams/task/executor/RemoteWorker.java | 217 ++ .../ams/task/executor/TaskJobSubmit.java | 46 + .../ams/task/executor/WorkerDispatcher.java | 162 ++ .../com/bocloud/ams/task/input/DBInput.java | 19 + .../com/bocloud/ams/task/input/Depend.java | 77 + .../com/bocloud/ams/task/input/HttpInput.java | 22 + .../com/bocloud/ams/task/input/Input.java | 46 + .../bocloud/ams/task/input/ScriptInput.java | 21 + .../com/bocloud/ams/task/input/Target.java | 94 + .../task/listener/AbstractTaskListener.java | 47 + .../task/listener/MaintainTaskListener.java | 58 + .../com/bocloud/ams/task/model/DBFront.java | 122 + .../bocloud/ams/task/model/HostResult.java | 166 ++ .../com/bocloud/ams/task/model/HttpFront.java | 84 + .../java/com/bocloud/ams/task/model/Job.java | 156 ++ .../com/bocloud/ams/task/model/JobResult.java | 68 + .../com/bocloud/ams/task/model/Module.java | 77 + .../com/bocloud/ams/task/model/Option.java | 88 + .../bocloud/ams/task/model/ScriptFront.java | 73 + .../bocloud/ams/task/model/TargetGroup.java | 59 + .../bocloud/ams/task/model/WorkerHost.java | 240 ++ .../bocloud/ams/task/model/WorkerScript.java | 109 + .../ams/task/model/enums/TaskParam.java | 74 + .../com/bocloud/ams/task/utils/DBDriver.java | 45 + .../com/bocloud/ams/task/utils/DBTool.java | 84 + .../bocloud/ams/task/utils/ParamBuilder.java | 39 + .../ams/task/worker/AbstractWorker.java | 76 + .../ams/task/worker/DatabaseWorker.java | 426 +++ .../ams/task/worker/InputClassLocator.java | 51 + .../ams/task/worker/MaintainWorker.java | 144 + .../bocloud/ams/task/worker/MethodWorker.java | 118 + .../bocloud/ams/task/worker/ScriptWorker.java | 95 + .../ams/task/worker/WorkerClassLocator.java | 51 + .../ams/task/worker/WorkerFactory.java | 52 + pom.xml | 144 + 259 files changed, 33389 insertions(+) create mode 100644 bocloud.ams.booter/.gitignore create mode 100644 bocloud.ams.booter/pom.xml create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/Application.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/RabbitMQConfiguration.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/SwaggerConfiguration.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/WebInterceptorConfiguration.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/association/AutoRelationRuleController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/audit/OperationalAuditController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryItemController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskInstanceController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTemplateController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/config/CmdbConfigController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceAuthoryController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceHistoryController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationHistoryRecordController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleGroupController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleRelationController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyPoolController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RegularExpressionController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationCategoryController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/TopologyConfigController.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/listener/TaskResultListener.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/CollectionTaskInstanceBakScheduler.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/ModuleInstanceRelationScheduler.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/OperationalAuditBakScheduler.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogAppenderTcpAndUdp.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogLevelConvertor.java create mode 100644 bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SyslogOutputStreamTcpAndUdp.java create mode 100644 bocloud.ams.booter/src/main/resources/application.yml create mode 100644 bocloud.ams.booter/src/main/resources/banner.txt create mode 100644 bocloud.ams.booter/src/main/resources/logback-spring.xml create mode 100644 bocloud.ams.entity/.gitignore create mode 100644 bocloud.ams.entity/pom.xml create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/annotation/ColumnType.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/Role.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/TableLog.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRule.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItem.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItemValue.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAudit.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAuditBak.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionComponent.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistory.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryBak.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItem.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItemBak.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTask.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstance.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstanceBak.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTemplate.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/config/CmdbConfig.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/ApplyStatus.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/CollectionEnum.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/InstanceEnum.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/OperationalAuditType.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/PropertyType.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/Status.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/Instance.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceAuthority.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceHistory.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelation.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelationHistoryRecord.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceValue.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/CollectionHistoryModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnAndSearchItemModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceBean.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceLink.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceNodeModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryAlterModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryPreflightModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceTopo.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleLink.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleTopo.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/NotifyMessage.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/OperateParam.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PathModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PropertyModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/RequestInstanceTopologyModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ResponseInstanceTopologyModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/Role.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/SearchConfigModel.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/StartModeParams.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskBean.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskGraph.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskInstanceBean.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskNode.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskTransferParams.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/CiModule.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleGroup.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleRelation.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Property.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyGroup.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyItem.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPool.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPoolItem.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RegularExpression.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Relation.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RelationCategory.java create mode 100644 bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/TopologyConfig.java create mode 100644 bocloud.ams.repository/.gitignore create mode 100644 bocloud.ams.repository/pom.xml create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/TableLogRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemValueRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditBakRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionComponentRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryBakRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemBakRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceBakRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTemplateRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/config/CmdbConfigRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceAuthorityRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceHistoryRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationHistoryRecordRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceValueRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleGroupRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRelationRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyGroupRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyItemRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolItemRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RegularExpressionRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationCategoryRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/TopologyConfigRepository.java create mode 100644 bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/utils/CmdbUtils.java create mode 100644 bocloud.ams.service/.gitignore create mode 100644 bocloud.ams.service/pom.xml create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleItemService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleItemServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/OperationalAuditService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/impl/OperationalAuditServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryItemService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskInstanceService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTemplateService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryItemServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskInstanceServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTemplateServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/CmdbConfigService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/impl/CmdbConfigServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/core/CmdbConfigCache.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAuthorityService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAutoRelationService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceHistoryService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationHistoryRecordService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceValueService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAuthorityServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAutoRelationServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceHistoryServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationHistoryRecordServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceValueServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/AmsInternalService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/SmsInternalService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleGroupService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleRelationService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyPoolService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RegularExpressionService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationCategoryService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/TopologyConfigService.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleGroupServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleRelationServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyPoolServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RegularExpressionServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationCategoryServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/TopologyConfigServiceImpl.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/InstanceRelationTask.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/ModuleInstanceRelationTask.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/AutoModuleInstanceRelationUtils.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/BoStringUtils.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/CollectionHistoryHelper.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/EventPublisher.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelFactory.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelHelper.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/GraphAlgorithmUtils.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceExcelHelper.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceHistoryHelper.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/JsonCompareUtil.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ModuleConstant.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/PropertyConstant.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RelationHistoryConstant.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RepositoryHandler.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/StreamUtils.java create mode 100644 bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/paginationUtil.java create mode 100644 bocloud.ams.task/.gitignore create mode 100644 bocloud.ams.task/pom.xml create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Module.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Worker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/exception/NodeFormatException.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/RemoteWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/TaskJobSubmit.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/WorkerDispatcher.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/DBInput.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Depend.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/HttpInput.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Input.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/ScriptInput.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Target.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/AbstractTaskListener.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/MaintainTaskListener.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/DBFront.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HostResult.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HttpFront.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Job.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/JobResult.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Module.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Option.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/ScriptFront.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/TargetGroup.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerHost.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerScript.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/enums/TaskParam.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBDriver.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBTool.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/ParamBuilder.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/AbstractWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/DatabaseWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/InputClassLocator.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MaintainWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MethodWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/ScriptWorker.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerClassLocator.java create mode 100644 bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerFactory.java create mode 100644 pom.xml diff --git a/bocloud.ams.booter/.gitignore b/bocloud.ams.booter/.gitignore new file mode 100644 index 0000000..e313482 --- /dev/null +++ b/bocloud.ams.booter/.gitignore @@ -0,0 +1,10 @@ +*/target/* +*/.settings/* +*.classpath +*.project +*.prefs +*.class +*.iml +/.idea/* +*/.svn/* +/target/ diff --git a/bocloud.ams.booter/pom.xml b/bocloud.ams.booter/pom.xml new file mode 100644 index 0000000..7266529 --- /dev/null +++ b/bocloud.ams.booter/pom.xml @@ -0,0 +1,157 @@ + + + + bocloud.ams + com.bocloud + 6.5.0-LTS-SZ + + 4.0.0 + bocloud.ams.booter + ${bocloud.booter.version} + + + + org.springframework.boot + spring-boot-starter-web + + + org.hibernate.validator + hibernate-validator + + + + + + com.bocloud + bocloud.ams.service + + + com.freedom + megatron.microservice + + + junit + junit + test + + + org.springframework.boot + spring-boot-test + 2.3.5.RELEASE + test + + + org.springframework + spring-test + 5.2.10.RELEASE + test + + + + org.slf4j + slf4j-api + 2.0.7 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + true + 21 + 21 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + com.bocloud.ams.booter.Application + true + false + libs/ + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.6.1 + + + + copy-dependencies + + + jar + jar + runtime + ${project.build.directory}/libs + + + + + + + + + bocloud.booter.tomcat + + 6.5.0-LTS-SZ + + + + org.springframework.boot + spring-boot-starter-web + + + org.hibernate.validator + hibernate-validator + + + + + + + bocloud.booter.tongweb + + 6.5.0-LTS-SZ-TONGWEB + + + + com.tongweb + tongweb-embed + 7.0.E.2 + + + com.tongweb.springboot + tongweb-spring-boot-starter + 2.x.0.RELEASE + + + org.springframework.boot + spring-boot-starter-web + + + org.hibernate.validator + hibernate-validator + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + + \ No newline at end of file diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/Application.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/Application.java new file mode 100644 index 0000000..f51ca06 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/Application.java @@ -0,0 +1,24 @@ +package com.bocloud.ams.booter; + +import org.springframework.amqp.rabbit.annotation.EnableRabbit; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * CMDB服务启动类 + * + * @author DMW + */ +@SpringBootApplication +@EnableRabbit +@EnableDiscoveryClient +@EnableScheduling +@ComponentScan(value = {"com.bocloud", "com.megatron"}) +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/RabbitMQConfiguration.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/RabbitMQConfiguration.java new file mode 100644 index 0000000..f7413cb --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/RabbitMQConfiguration.java @@ -0,0 +1,145 @@ +package com.bocloud.ams.booter.config; + +import com.bocloud.ams.booter.listener.TaskResultListener; +import com.megatron.common.utils.MapTools; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "spring.rabbitmq") +public class RabbitMQConfiguration { + private Map arguments = MapTools.simpleMap("x-ha-policy", "all"); + @Autowired + private ConnectionFactory connectionFactory; + + /** + * 声明审计日志队列 + * + * @return + */ + @Bean + public Queue declareLogQueue() { + return new Queue("bocloud.log.queue", true, false, false, arguments); + } + + + /** + * 声明默认的交换 + * + * @return + */ + @Bean + public DirectExchange deafultExchange() { + return new DirectExchange("bocloud.direct.exchange", true, true, arguments); + } + + /** + * 绑定日志队列 + * + * @return + */ + @Bean + public Binding bindingLogQueue() { + return BindingBuilder.bind(declareLogQueue()).to(deafultExchange()).withQueueName(); + } + + /** + * 绑定CMDB任务队列 + * + * @return + */ + @Bean + public Binding bindingCmdbQueue() { + return BindingBuilder.bind(declareTaskResultQueue()).to(deafultExchange()).withQueueName(); + } + + /** + * 声明任务执行队列 + * + * @return + */ + @Bean + public Queue declareTaskResultQueue() { + return new Queue("cmdb.task.result.queue", true, false, false, arguments); + } + + @Bean + public MessageConverter messageConverter() { + return new Jackson2JsonMessageConverter(); + } + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public RabbitTemplate amqpTemplate() { + RabbitTemplate amqpTemplate = new RabbitTemplate(connectionFactory); + amqpTemplate.setMessageConverter(messageConverter()); + amqpTemplate.setExchange(deafultExchange().getName()); + return amqpTemplate; + } + + /** + * 设置手动消费确认 + * + * @param connectionFactory + * @return + */ + @Bean + public RabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + factory.setConnectionFactory(connectionFactory); + factory.setMessageConverter(new Jackson2JsonMessageConverter()); + factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); + return factory; + } + + @Bean + public SimpleMessageListenerContainer autoJobCompletedListener(TaskResultListener taskResultListener) { + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + container.setQueues(declareTaskResultQueue()); + // 设置确认模式自动确认 + container.setAcknowledgeMode(AcknowledgeMode.AUTO); + container.setMessageListener(taskResultListener); + return container; + } + + @Bean("customContainerFactory") + public SimpleRabbitListenerContainerFactory containerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + //设置线程数 + factory.setConcurrentConsumers(10); + //最大线程数 + factory.setMaxConcurrentConsumers(10); + configurer.configure(factory, connectionFactory); + return factory; + } + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public RabbitAdmin rabbitAdmin() { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + return rabbitAdmin; + } + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public AmqpAdmin amqpAdmin() { + AmqpAdmin amqpAdmin = new RabbitAdmin(connectionFactory); + return amqpAdmin; + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/SwaggerConfiguration.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/SwaggerConfiguration.java new file mode 100644 index 0000000..34bb9c7 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/SwaggerConfiguration.java @@ -0,0 +1,20 @@ +package com.bocloud.ams.booter.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; + +@Configuration +public class SwaggerConfiguration { + + @Bean + public OpenAPI openAPI() { + Contact contact = new Contact().name("未伟").email("weiwei@beyondcent.com").url("http://www.bocloud.com/"); + Info info = new Info().title("CMDB服务API接口文档").description("CMDB服务API接口文档") + .termsOfService("http://www.bocloud.com/").contact(contact).version("1.0"); + return new OpenAPI().info(info); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/WebInterceptorConfiguration.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/WebInterceptorConfiguration.java new file mode 100644 index 0000000..aae1b70 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/config/WebInterceptorConfiguration.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.booter.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.bocloud.cmp.boot.config.PagerArgumentResolver; +import com.bocloud.cmp.boot.interceptor.AccessInterceptor; +import com.bocloud.cmp.boot.interceptor.LogInterceptor; +import com.megatron.framework.core.InterceptorBridge; +import com.megatron.framework.core.config.InterceptorConfiguration; +import com.megatron.framework.core.domain.InterceptorEntity; + +import lombok.extern.slf4j.Slf4j; + +/** + * 拦截器配置类 + * + * @author dmw + */ +@Slf4j +@Component +public class WebInterceptorConfiguration implements InterceptorConfiguration { + + private static final String[] ACCESS_EXCLUDES = new String[] {"/status", "/status/db", "/status/**", + "/v1/status/**", "/login", "/sso", "/v1/logview", "/v1/logzip", "/v1/config/**", "/v1/plugins/**", "/*/*.css", + "/*/*.js", "/*/*.png", "/*/*.jpg", "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**", "/favicon.ico", + "/webjars/**", "/v3/**", "/swagger-ui.html/**", "**/api-docs", "/error", "/favicon.ico"}; + private static final String[] LOG_EXCLUDES = new String[] {"/*/*.css", "/*/*.js", "/*/*.png", "/*/*.jpg", + "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**", "/favicon.ico", "/webjars/**", "/v3/**", + "/swagger-ui.html/**", "**/api-docs", "/error", "/favicon.ico"}; + private static final String[] INCLUDES = new String[] {"/**"}; + private final LogInterceptor logInterceptor; + private final AccessInterceptor accessInterceptor; + + @Autowired + public WebInterceptorConfiguration(AccessInterceptor accessInterceptor, LogInterceptor logInterceptor) { + this.logInterceptor = logInterceptor; + this.accessInterceptor = accessInterceptor; + } + + @Override + public InterceptorBridge buildBridge() { + log.info("start to build interceptors..."); + InterceptorBridge bridge = new InterceptorBridge(); + InterceptorEntity accessEntity = InterceptorEntity.builder().interceptor(accessInterceptor).includes(INCLUDES) + .excludes(ACCESS_EXCLUDES).order(0).build(); + InterceptorEntity auditLogEntity = InterceptorEntity.builder().interceptor(logInterceptor).includes(INCLUDES) + .excludes(LOG_EXCLUDES).order(1).build(); + List interceptors = new ArrayList<>(); + interceptors.add(accessEntity); + interceptors.add(auditLogEntity); + bridge.setInterceptors(interceptors); + bridge.setResolvers(Collections.singletonList(new PagerArgumentResolver())); + bridge.setMessageConverters(new ArrayList<>(0)); + log.info("build interceptors success!!!"); + return bridge; + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/association/AutoRelationRuleController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/association/AutoRelationRuleController.java new file mode 100644 index 0000000..233becc --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/association/AutoRelationRuleController.java @@ -0,0 +1,112 @@ +package com.bocloud.ams.booter.controller.association; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.service.association.AutoRelationRuleService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/rule") +@Tag(name = "关联规则管理") +public class AutoRelationRuleController { + + @Autowired + private AutoRelationRuleService autoRelationRuleService; + + /** + * 关联规则展示 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则列表") + @GetMapping + public GeneralResult> list(Pager pager) { + return autoRelationRuleService.list(pager); + } + + /** + * 新增关联规则 + * + * @param rule + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则新增") + @PostMapping + public GeneralResult save(@RequestBody AutoRelationRule rule, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return autoRelationRuleService.save(rule, context.getTarget()); + } + + /** + * 更新关联规则 + * + * @param id + * @param rule + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则修改") + @PutMapping(value = "/{id}") + public GeneralResult modify(@PathVariable(value = Common.ID) Long id, @RequestBody AutoRelationRule rule, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return autoRelationRuleService.modify(id, rule, context.getTarget()); + } + + /** + * 关联规则详情 + * + * @param id + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则详情") + @GetMapping(value = "/{id}") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return autoRelationRuleService.detail(id); + } + + /** + * 关联规则明细详情 + * + * @param itemId + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则明细详情") + @GetMapping(value = "/{id}/items/{itemId}") + public GeneralResult itemDetail(@PathVariable("itemId") Long itemId) { + return autoRelationRuleService.itemDetail(itemId); + } + + /** + * 删除关联规则 + * + * @param id + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "关联规则删除") + @DeleteMapping(value = "/{id}") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return autoRelationRuleService.remove(id, context.getTarget()); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/audit/OperationalAuditController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/audit/OperationalAuditController.java new file mode 100644 index 0000000..bed20a4 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/audit/OperationalAuditController.java @@ -0,0 +1,57 @@ +package com.bocloud.ams.booter.controller.audit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.audit.OperationalAuditBak; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/operational/audit") +@Tag(name = "操作审计管理") +public class OperationalAuditController { + + @Autowired + private OperationalAuditService operationalAuditService; + + /** + * 资源变更记录 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "操作审计列表") + @GetMapping + public GeneralResult> operationalAudit(Pager pager) { + return operationalAuditService.list(pager); + } + + /** + * 资源变更记录详情 + * + * @param id + * @return + */ + @Operation(tags = {"CMC"}, summary = "操作审计详情") + @GetMapping(value = "/{id}") + public GeneralResult operationalAudit(@PathVariable(value = Common.ID) Long id) { + return operationalAuditService.deatil(id); + } + + @Operation(tags = {"CMC"}, summary = "操作审计备份列表") + @GetMapping(value = "/bak") + public GeneralResult> operationalAuditBak(Pager pager) { + return operationalAuditService.bakList(pager); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryController.java new file mode 100644 index 0000000..9cebe0b --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryController.java @@ -0,0 +1,81 @@ +package com.bocloud.ams.booter.controller.collection; + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.collection.CollectionHistory; +import com.bocloud.ams.entity.model.CollectionHistoryModel; +import com.bocloud.ams.service.collection.CollectionHistoryService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/collection/history") +@Tag(name = "采集历史管理") +public class CollectionHistoryController { + + @Autowired + private CollectionHistoryService collectionHistoryService; + + @Operation(tags = {"CMC"}, summary = "实例采集历史列表") + @GetMapping("/instances") + public GeneralResult>> list(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionHistoryService.instances(pager, context.getTarget()); + } + + @Operation(tags = {"CMC"}, summary = "采集历史列表") + @GetMapping + public GeneralResult> history(Pager pager) { + return collectionHistoryService.list(pager); + } + + @Operation(tags = {"CMC"}, summary = "采集历史新增") + @PostMapping + public GeneralResult save(@RequestBody CollectionHistory history, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionHistoryService.create(history); + } + + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "采集历史修改") + public GeneralResult modify(@RequestBody CollectionHistory history, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionHistoryService.modify(history); + } + + @PutMapping(value = "/batch") + @Operation(tags = {"CMC"}, summary = "采集历史批量新增") + public GeneralResult batchModify(@RequestBody CollectionHistoryModel historyModel, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionHistoryService.batchModify(historyModel, context.getTarget()); + } + + @Operation(tags = {"CMC"}, summary = "采集历史备份列表") + @GetMapping("/backup") + public GeneralResult> backupHistory(Pager pager) { + return collectionHistoryService.backupHistory(pager); + } + + @Operation(tags = {"CMC"}, summary = "实例采集历史备份列表") + @GetMapping("/backup/instances") + public GeneralResult>> backupList(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionHistoryService.backupList(pager, context.getTarget()); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryItemController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryItemController.java new file mode 100644 index 0000000..d589783 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionHistoryItemController.java @@ -0,0 +1,37 @@ +package com.bocloud.ams.booter.controller.collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.bocloud.ams.service.collection.CollectionHistoryItemService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/collection/history/item") +@Tag(name = "采集历史条目管理") +public class CollectionHistoryItemController { + + @Autowired + private CollectionHistoryItemService collectionHistoryItemService; + + @Operation(tags = {"CMC"}, summary = "采集历史条目列表") + @GetMapping + public GeneralResult> historyItems(Pager pager) { + return collectionHistoryItemService.list(pager); + } + + @Operation(tags = {"CMC"}, summary = "实例采集历史条目备份列表") + @GetMapping("/backup") + public GeneralResult> backupHistoryItems(Pager pager) { + return collectionHistoryItemService.backupHistoryItems(pager); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskController.java new file mode 100644 index 0000000..9a4c125 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskController.java @@ -0,0 +1,161 @@ +package com.bocloud.ams.booter.controller.collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.model.OperateParam; +import com.bocloud.ams.service.collection.CollectionTaskService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/collection/tasks") +@Tag(name = "采集任务管理") +public class CollectionTaskController implements ApplicationListener { + + @Autowired + private CollectionTaskService collectionTaskService; + + /** + * 启动作业 + * + * @param id + * @param context + * @return + */ + @PatchMapping(value = "/{id}/start") + @Operation(tags = {"CMC", "CSC"}, summary = "采集任务执行") + public GeneralResult start(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTaskService.start(id, context); + } + + /** + * 采集任务列表 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "采集任务列表") + @GetMapping + public GeneralResult> list(Pager pager) { + return collectionTaskService.list(pager); + } + + /** + * 采集任务创建 + * + * @param task + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC"}, summary = "采集任务创建") + public GeneralResult create(@RequestBody CollectionTask task, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTaskService.save(task, context); + } + + /** + * 采集任务修改 + * + * @param bean + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "采集任务修改") + public GeneralResult modify(@RequestBody CollectionTask bean, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTaskService.modify(bean, context); + } + + /** + * 采集任务类型变更->由定时任务变更为常规任务 + * + * @param context + * @return + */ + @PatchMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "采集任务定时任务转为常规任务") + public GeneralResult modifyType(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTaskService.modifyType(id, context); + } + + /** + * 采集任务删除 + * + * @param id + * @param context + * @return + */ + @DeleteMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集任务删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTaskService.remove(id, context.getTarget()); + } + + /** + * 采集任务详情 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集任务详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return collectionTaskService.detail(id); + } + + /** + * 采集定时任务操作-启动/暂停 + * + * @param operateParam + * @param requestContext + * @return + */ + @PatchMapping(value = "/{id}/schedule") + @Operation(summary = "采集任务定时任务操作-启动/暂停") + public GeneralResult operate(@RequestBody OperateParam operateParam, @PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext requestContext) { + return collectionTaskService.operate(operateParam, id, requestContext.getTarget()); + } + + @GetMapping(value = "/{id}/schedule") + @Operation(tags = {"CMC"}, summary = "采集任务为定时采集添加任务(主服务有效)") + public GeneralResult addScheduleIfLeader(@PathVariable(Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext requestContext) { + return collectionTaskService.addScheduleIfLeader(id); + } + + @DeleteMapping(value = "/{id}/schedule") + @Operation(tags = {"CMC"}, summary = "采集任务为定时采集删除任务(主服务有效)") + public GeneralResult removeScheduleIfLeader(@PathVariable(Common.ID) Long id) { + return collectionTaskService.removeScheduleIfLeader(id); + } + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + collectionTaskService.onApplicationReadyEvent(); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskInstanceController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskInstanceController.java new file mode 100644 index 0000000..351aa9d --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTaskInstanceController.java @@ -0,0 +1,57 @@ +package com.bocloud.ams.booter.controller.collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.service.collection.CollectionTaskInstanceService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/collection/tasks/instances") +@Tag(name = "采集任务实例管理") +public class CollectionTaskInstanceController { + + @Autowired + private CollectionTaskInstanceService collectionTaskInstanceService; + + /** + * 采集任务实例列表 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "采集任务实例列表") + @GetMapping + public GeneralResult> list(Pager pager) { + return collectionTaskInstanceService.list(pager); + } + + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集任务实例详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return collectionTaskInstanceService.detail(id); + } + + @Operation(tags = {"CMC"}, summary = "采集任务实例备份列表") + @GetMapping("/backup") + public GeneralResult> bakList(Pager pager) { + return collectionTaskInstanceService.bakList(pager); + } + + @GetMapping(value = "/{name}/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集任务实例备份详情") + public GeneralResult bakDetail(@PathVariable(value = Common.ID) Long id, + @PathVariable(value = Common.NAME) String name) { + return collectionTaskInstanceService.bakDetail(id, name); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTemplateController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTemplateController.java new file mode 100644 index 0000000..a28b203 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/collection/CollectionTemplateController.java @@ -0,0 +1,113 @@ +package com.bocloud.ams.booter.controller.collection; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.bocloud.ams.entity.collection.CollectionTemplate; +import com.bocloud.ams.service.collection.CollectionTemplateService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/collection/templates") +@Tag(name = "采集插件管理") +public class CollectionTemplateController { + + @Autowired + private CollectionTemplateService collectionTemplateService; + + /** + * 采集模板组件列表 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "采集插件组件列表") + @GetMapping(value = "/components") + public GeneralResult> components(Pager pager) { + return collectionTemplateService.components(pager); + } + + /** + * 采集插件列表 + * + * @param pager + * @return + */ + @Operation(tags = {"CMC"}, summary = "采集插件列表") + @GetMapping + public GeneralResult> list(Pager pager) { + return collectionTemplateService.list(pager); + } + + /** + * 新增采集插件 + * + * @param template + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "采集插件新增") + @PostMapping + public GeneralResult save(@RequestBody CollectionTemplate template, + @Value(Common.REQ_CONTEXT) RequestContext context) { + template.setCreatorId(context.getTarget()); + return collectionTemplateService.save(template, context.getTarget()); + } + + /** + * 采集插件修改 + * + * @param template + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集插件修改") + public GeneralResult modify(@RequestBody CollectionTemplate template, + @Value(Common.REQ_CONTEXT) RequestContext context) { + template.setMenderId(context.getTarget()); + return collectionTemplateService.modify(template, context.getTarget()); + } + + /** + * 采集插件删除 + * + * @param id + * @param context + * @return + */ + @DeleteMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集插件删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return collectionTemplateService.remove(id, context.getTarget()); + } + + /** + * 采集插件详情 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "采集插件详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return collectionTemplateService.detail(id); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/config/CmdbConfigController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/config/CmdbConfigController.java new file mode 100644 index 0000000..d60ad1a --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/config/CmdbConfigController.java @@ -0,0 +1,75 @@ +package com.bocloud.ams.booter.controller.config; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.alibaba.fastjson.JSONArray; +import com.bocloud.ams.entity.config.CmdbConfig; +import com.bocloud.ams.service.config.CmdbConfigService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.Result; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/cmdb/configs") +@Tag(name = "配置中心配置管理") +public class CmdbConfigController { + + @Autowired + private CmdbConfigService cmdbConfigService; + + /** + * 更新CMDB配置 + * + * @param configs + * @param context + * @return + */ + @PutMapping + @Operation(tags = {"CMC", "CSC"}, summary = "配置中心配置修改") + public Result modify(@RequestBody List configs, @Value(Common.REQ_CONTEXT) RequestContext context) { + return cmdbConfigService.batchUpdate(configs, context); + } + + /** + * 查询CMDB配置 + * + * @param category + * @param codes + * @return + */ + @GetMapping + @Operation(summary = "配置中心配置批量查询") + public GeneralResult> getByCodes( + @RequestParam(value = "category", required = false) String category, + @RequestParam(value = "codes", required = false) ArrayList codes) { + return cmdbConfigService.listConfigs(category, codes); + } + + /** + * 查询CMDB配置类型树 + * + * @param category + * @return + */ + @GetMapping("/tree") + @Operation(summary = "配置中心配置类型树") + public GeneralResult listCategoryTree(@RequestParam(value = "category") String category) { + return cmdbConfigService.listCategoryTree(category); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceAuthoryController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceAuthoryController.java new file mode 100644 index 0000000..1b264e2 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceAuthoryController.java @@ -0,0 +1,89 @@ +package com.bocloud.ams.booter.controller.instance; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.instance.InstanceAuthority; +import com.bocloud.ams.service.instance.InstanceAuthorityService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/instances/authority") +@Tag(name = "实例权限管理") +public class InstanceAuthoryController { + + @Autowired + private InstanceAuthorityService instanceAuthorityService; + + /** + * 实例权限列表 + * + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例权限列表") + @GetMapping + public GeneralResult> list(Pager pager) { + return instanceAuthorityService.list(pager); + } + + /*** + * 新增实例权限 + * + * @param authority + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例权限新增") + @PostMapping + public GeneralResult save(@RequestBody InstanceAuthority authority, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceAuthorityService.create(authority, context.getTarget()); + } + + @Operation(tags = {"CMC"}, summary = "实例权限修改") + @PutMapping(value = "/{id}") + public GeneralResult modify(@RequestBody InstanceAuthority authority, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceAuthorityService.modify(authority, context.getTarget()); + } + + /** + * 删除实例权限 + * + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例权限删除") + @DeleteMapping(value = "/{id}") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceAuthorityService.remove(id, context.getTarget()); + } + + /** + * 批量删除实例权限 + * + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例权限批量删除") + @DeleteMapping(value = "/byrole") + public GeneralResult removeByRole(@RequestBody InstanceAuthority authority, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceAuthorityService.removeByRole(authority, context.getTarget()); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceController.java new file mode 100644 index 0000000..05dd11e --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceController.java @@ -0,0 +1,226 @@ +package com.bocloud.ams.booter.controller.instance; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.model.InstanceBean; +import com.bocloud.ams.entity.model.InstanceTopo; +import com.bocloud.ams.service.instance.InstanceService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequestMapping("/v1/instances") +@Tag(name = "实例管理") +public class InstanceController { + + @Autowired + private InstanceService instanceService; + + @Operation(tags = {"CMC"}, summary = "实例列表") + @GetMapping + public GeneralResult>> list(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.list(pager, context.getTarget()); + } + + /*** + * 新增实例 + * + * @param instance + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例新增") + @PostMapping + public GeneralResult save(@RequestBody JSONObject instance, @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.create(instance, context.getTarget(), true); + } + + /*** + * 更新实例 + * + * @param instance + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例修改") + @PutMapping(value = "/{id}") + public GeneralResult modify(@RequestBody JSONObject instance, @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.modify(instance, context.getTarget()); + } + + /*** + * 批量更新实例 + * + * @param instance + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例批量更新") + @PutMapping(value = "/batch") + public GeneralResult batchModify(@RequestBody InstanceBean instance, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.batchModify(instance, context.getTarget()); + } + + /** + * 删除实例 + * + * @param id + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例删除") + @DeleteMapping(value = "/{id}") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "moduleCode") String moduleCode, @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.remove(id, moduleCode, context.getTarget()); + } + + /** + * 批量删除实例 + * + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例批量删除") + @DeleteMapping(value = "/batch") + public GeneralResult batchRemove(@RequestBody InstanceBean model, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.batchRemove(model, context.getTarget()); + } + + /** + * 实例查询明细 + * + * @param id + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例详情") + @GetMapping(value = "/{id}") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "moduleCode") String moduleCode) { + return instanceService.detail(id, moduleCode); + } + + @Operation(summary = "实例导出") + @GetMapping(value = "/export") + public void export(@RequestParam(value = "moduleId") Long moduleId, + @RequestParam(value = "moduleCode") String moduleCode, @RequestParam(value = "type") String type, + HttpServletRequest request, HttpServletResponse response, @Value(Common.REQ_CONTEXT) RequestContext context) { + @SuppressWarnings("unchecked") + GeneralResult GeneralResult = instanceService.export(moduleId, moduleCode, type, context.getTarget()); + if (GeneralResult.isSuccess()) { + String content = null; + try { + @SuppressWarnings("unchecked") + Map result = + JSONObject.parseObject(JSONObject.toJSONString(GeneralResult.getData()), HashMap.class); + response.setContentType("application/vnd.ms-excel"); + String fileName = result.get("fileName").toString(); + final String userAgent = request.getHeader("user-agent").toLowerCase(); + if (userAgent.contains("trident") || userAgent.contains("edge")) { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } else { + fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1"); + } + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); + OutputStream outputStream = response.getOutputStream(); + content = (String)result.get("data"); + + if (content != null) { + byte[] bytes = Base64.getDecoder().decode(content); + outputStream.write(bytes); + outputStream.close(); + } + } catch (Exception e) { + log.error("导出实例数据失败"); + } + } + + } + + @Operation(summary = "实例模板下载") + @GetMapping(value = "/download") + public void download(@RequestParam(value = "moduleId") Long moduleId, + @RequestParam(value = "moduleCode") String moduleCode, @RequestParam(value = "type") String type, + HttpServletRequest request, HttpServletResponse response, @Value(Common.REQ_CONTEXT) RequestContext context) { + @SuppressWarnings("unchecked") + GeneralResult GeneralResult = instanceService.download(moduleId, moduleCode, type, context.getTarget()); + if (GeneralResult.isSuccess()) { + String content = null; + try { + @SuppressWarnings("unchecked") + Map result = + JSONObject.parseObject(JSONObject.toJSONString(GeneralResult.getData()), HashMap.class); + response.setContentType("application/vnd.ms-excel"); + String fileName = result.get("fileName").toString(); + final String userAgent = request.getHeader("user-agent").toLowerCase(); + if (userAgent.contains("trident") || userAgent.contains("edge")) { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } else { + fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1"); + } + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); + OutputStream outputStream = response.getOutputStream(); + content = (String)result.get("data"); + + if (content != null) { + byte[] bytes = Base64.getDecoder().decode(content); + outputStream.write(bytes); + outputStream.close(); + } + } catch (Exception e) { + log.error("下载实例模板失败"); + } + } + } + + @Operation(summary = "实例导入") + @PostMapping(value = "/upload") + public GeneralResult upload(@RequestParam(value = "moduleId") Long moduleId, + @RequestParam(value = "moduleCode") String moduleCode, + @RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request, + HttpServletResponse response, @Value(Common.REQ_CONTEXT) RequestContext context) throws IOException { + return instanceService.upload(moduleId, moduleCode, file, context); + } + + @Operation(summary = "实例拓扑") + @GetMapping(value = "/{id}/topo") + public GeneralResult topo(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "relationCategoryId") Long relationCategoryId, + @RequestParam(value = "moduleId") Long moduleId, @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceService.topo(id, relationCategoryId, moduleId, context.getTarget()); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceHistoryController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceHistoryController.java new file mode 100644 index 0000000..4ef36e4 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceHistoryController.java @@ -0,0 +1,36 @@ +package com.bocloud.ams.booter.controller.instance; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.instance.InstanceHistory; +import com.bocloud.ams.service.instance.InstanceHistoryService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/instances/history") +@Tag(name = "实例变更记录管理") +public class InstanceHistoryController { + + @Autowired + private InstanceHistoryService instanceHistoryService; + + /** + * 模型实例变更记录 + * + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例变更记录列表") + @GetMapping + public GeneralResult> history(Pager pager) { + return instanceHistoryService.list(pager); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationController.java new file mode 100644 index 0000000..352602f --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationController.java @@ -0,0 +1,88 @@ + +package com.bocloud.ams.booter.controller.instance; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.bocloud.ams.service.instance.InstanceRelationService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping(value = "/v1/instances/relations") +@Tag(name = "实例关系管理") +public class InstanceRelationController { + + @Autowired + private InstanceRelationService instanceRelationService; + + @Autowired + private InstanceAutoRelationService instanceAutoRelationService; + + /*** + * 新增实例关系 + * + * @param relation + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例关系关联") + @PostMapping + public GeneralResult save(@RequestBody InstanceRelation relation, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationService.create(relation, context); + } + + /*** + * 删除实例关系 + * + * @param id + * @param relationCategoryCode + * @param currentInstanceId + * @param context + * @return + */ + @Operation(tags = {"CMC"}, summary = "实例关系取消关联") + @DeleteMapping(value = "/{id}") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "relationCategoryCode") String relationCategoryCode, + @RequestParam(value = "currentModuleId") Long currentModuleId, + @RequestParam(value = "currentInstanceId") Long currentInstanceId, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationService.remove(id, relationCategoryCode, currentModuleId, currentInstanceId, context); + } + + @Operation(tags = {"CMC"}, summary = "实例关系实例数据自动关联") + @PostMapping(value = "/auto/relation") + public GeneralResult instanceAutoRelation(@RequestBody Instance instance, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceAutoRelationService.instanceAutoRelation(instance, context.getTarget()); + } + + @Operation(tags = {"CMC"}, summary = "实例关系全量数据自动关联") + @GetMapping(value = "/auto/relation/all") + public GeneralResult moduleAutoRelation() { + return instanceAutoRelationService.autoRelation(); + } + + @Operation(tags = {"CMC"}, summary = "实例关系模型数据自动关联") + @GetMapping(value = "/auto/relation/{id}/module") + public GeneralResult moduleAutoRelationByModuleId(@PathVariable(value = Common.ID) Long id) { + return instanceAutoRelationService.autoRelationByModuleId(id); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationHistoryRecordController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationHistoryRecordController.java new file mode 100644 index 0000000..ffa6814 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/instance/InstanceRelationHistoryRecordController.java @@ -0,0 +1,80 @@ +package com.bocloud.ams.booter.controller.instance; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.bocloud.ams.entity.model.InstanceRelationHistoryPreflightModel; +import com.bocloud.ams.service.instance.InstanceRelationHistoryRecordService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/instances/relations/history") +@Tag(name = "关联历史管理") +public class InstanceRelationHistoryRecordController { + + @Autowired + private InstanceRelationHistoryRecordService instanceRelationHistoryRecordService; + + /** + * 关联历史列表 + * + * @param pager + * @param context + * @return + */ + @GetMapping + @Operation(tags = {"CMC", "CSC"}, summary = "关联历史列表") + public GeneralResult> list(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationHistoryRecordService.list(pager); + } + + @PutMapping("/{id}/preflight") + @Operation(tags = {"CMC", "CSC"}, summary = "关联历史预检") + public GeneralResult preflight(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationHistoryRecordService.preflight(id, context); + + } + + @PutMapping("/{id}/reconcile") + @Operation(tags = {"CMC", "CSC"}, summary = "关联历史调和") + public GeneralResult reconcile(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationHistoryRecordService.reconcile(id, context); + + } + + @PutMapping("/{id}/cancel") + @Operation(tags = {"CMC", "CSC"}, summary = "关联历史取消调和") + public GeneralResult cancel(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationHistoryRecordService.cancel(id, context); + + } + + @Operation(tags = {"CMC"}, summary = "关联历史批量取消调和") + @PutMapping(value = "/batch/cancel") + public GeneralResult batchCancel(@RequestBody List ids, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return instanceRelationHistoryRecordService.batchCancel(ids, context); + + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleController.java new file mode 100644 index 0000000..169650f --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleController.java @@ -0,0 +1,192 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.model.PropertyModel; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.service.association.AutoRelationRuleService; +import com.bocloud.ams.service.module.ModuleService; +import com.bocloud.ams.service.module.RelationCategoryService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/module") +@Tag(name = "模型管理") +public class ModuleController { + + @Autowired + private ModuleService moduleService; + @Autowired + private RelationCategoryService relationCategoryService; + @Autowired + private AutoRelationRuleService autoRelationRuleService; + + /** + * 查询属性池记录 + * + * @param pager + * @param context + * @return + */ + @GetMapping("/collections") + @Operation(tags = {"CMC", "CSC"}, summary = "模型列表") + public GeneralResult> getModelList(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleService.getModelList(pager); + } + + /** + * 查询模型集合 + * + * @return + */ + @GetMapping + @Operation(tags = {"CMC"}, summary = "模型列表(全部)") + public GeneralResult> list() { + return moduleService.list(); + } + + /** + * 模型查询明细 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "模型详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return moduleService.detail(id); + } + + /** + * 新增模型 + * + * @param module + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC"}, summary = "模型新增") + public GeneralResult save(@RequestBody CiModule module, @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleService.save(module, context.getTarget()); + } + + /** + * 更新模型 + * + * @param module + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "模型修改") + public GeneralResult modify(@RequestBody CiModule module, @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleService.modify(module, context.getTarget()); + } + + /** + * 删除模型 + * + * @param id + * @return + */ + @DeleteMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "模型删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleService.remove(id, context.getTarget()); + } + + /** + * 根据模型Id查询关联分组 + * + * @param id + * 模型id + * @Description: 根据模型Id查询关联分组 + * @Author majiali + * @CreateTime 2022/6/15 16:07 + */ + @GetMapping(value = "/{id}/relation/category") + @Operation(tags = {"CMC"}, summary = "模型关联分组查询") + public GeneralResult> listRelationCategory(@PathVariable(value = Common.ID) Long id) { + return relationCategoryService.listByModuleId(id); + } + + /** + * 根据模型id和关联分组id查询关联规则 + * + * @param id + * @param relationCategoryId + * @return + */ + @Operation(tags = {"CMC"}, summary = "模型关联分组关联规则查询") + @GetMapping(value = "/{id}/relation/rule") + public GeneralResult> list(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "relationCategoryId") Long relationCategoryId) { + return autoRelationRuleService.list(id, relationCategoryId); + } + + /** + * 查看模型属性 + * + * @param id + * @return 查看模型属性 + */ + @GetMapping(value = "/{id}/properties") + @Operation(summary = "模型属性查询") + public GeneralResult property(@PathVariable(value = Common.ID) Long id) { + return moduleService.property(id); + } + + /** + * 查询模型属性集合 + * + * @param moduleId + * @param pager + * @return + */ + @GetMapping(value = "/{moduleId}/list") + @Operation(summary = "模型属性列表") + public GeneralResult> propertyList(@PathVariable(value = "moduleId") Long moduleId, + Pager pager) { + return moduleService.propertyList(moduleId, pager); + } + + /** + * 编辑模型属性 + * + * @param model + * @param id + * @param context + * @return + */ + @PutMapping(value = "/{id}/properties") + @Operation(summary = "模型属性修改") + public GeneralResult modifyProperty(@RequestBody PropertyModel model, + @PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleService.modifyProperty(model, id, context); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleGroupController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleGroupController.java new file mode 100644 index 0000000..84afba1 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleGroupController.java @@ -0,0 +1,159 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.ModuleGroup; +import com.bocloud.ams.service.module.ModuleGroupService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "模型分组管理") +@RestController +@RequestMapping("/v1/module/group") +public class ModuleGroupController { + @Autowired + private ModuleGroupService moduleGroupService; + + /** + * 模型分组采集结构查询 + * + * @param category + * @return + */ + @GetMapping(value = "/collections") + @Operation(tags = {"CMC"}, summary = "模型分组采集结构查询") + public GeneralResult> collections(@RequestParam(value = "category") String category, + @RequestParam(value = "moduleName", required = false) String moduleName) { + return moduleGroupService.collections(category, moduleName); + } + + /** + * 模型分组根节点结构查询 + * + * @return + */ + @GetMapping(value = "/roots") + @Operation(tags = {"CMC"}, summary = "模型分组根节点结构查询") + public GeneralResult> queryRoot() { + return moduleGroupService.queryRoot(); + } + + /** + * 当前根节点的子分组查询 + * + * @return + */ + @GetMapping + @Operation(tags = {"CMC"}, summary = "模型分组所有分组节点查询") + public GeneralResult> queryRootChildren() { + return moduleGroupService.queryRootChildren(); + } + + /** + * 模型分组子级数据(下级节点和模型数据)查询 + * + * @param groupId + * @return + */ + @GetMapping(value = "/{groupId}/children") + @Operation(tags = {"CMC"}, summary = "模型分组子级数据(下级节点和模型数据)查询") + public GeneralResult queryChildren(@PathVariable(value = "groupId") Long groupId, + @RequestParam(value = "menu", required = false) String menu, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleGroupService.queryChildren(groupId, menu, context); + } + + /** + * 模型分组查询明细 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "模型分组详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + return moduleGroupService.detail(id); + } + + /** + * 新增模型分组 + * + * @param group + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC"}, summary = "模型分组新增") + public GeneralResult save(@RequestBody ModuleGroup group, @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleGroupService.save(group, context.getTarget()); + } + + /** + * 更新模型分组 + * + * @param group + * @param context + * @return + */ + @PutMapping + @Operation(tags = {"CMC"}, summary = "模型分组修改") + public GeneralResult modify(@RequestBody ModuleGroup group, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleGroupService.modify(group, context.getTarget()); + } + + /** + * 删除模型分组 + * + * @param id + * @return + */ + @DeleteMapping(value = "/{id}") + @Operation(tags = {"CMC"}, summary = "模型分组删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleGroupService.remove(id, context.getTarget()); + } + + /** + * 新查询模型分组 + * + * @return + */ + @GetMapping(value = "/list") + @Operation(tags = {"CMC"}, summary = "模型分组查询") + public GeneralResult> querylist() { + return moduleGroupService.querylist(); + } + + /** + * 模型分组子级及父级数据(下级节点和模型数据)查询 + * + * @param groupId + * @return + */ + @GetMapping(value = "/{groupId}/root/children") + @Operation(tags = {"CMC"}, summary = "模型分组子级及父级数据(下级节点和模型数据)查询") + public GeneralResult> queryRootChildren(@PathVariable(value = "groupId") Long groupId, + @RequestParam(value = "menu", required = false) String menu, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleGroupService.queryRootChildren(groupId, menu, context); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleRelationController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleRelationController.java new file mode 100644 index 0000000..2687068 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/ModuleRelationController.java @@ -0,0 +1,192 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.model.ModuleTopo; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.service.module.ModuleRelationService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.ResultTools; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "模型关系管理") +@RestController +@RequestMapping("/v1/module/relation") +public class ModuleRelationController { + + @Autowired + private ModuleRelationService moduleRelationService; + + @GetMapping(value = "/relevancy") + @Operation(tags = {"CMC", "CSC"}, summary = "根据拓扑,模型数据查询模型关系") + public GeneralResult relevancy(@RequestParam("relationCategoryId") Long relationCategoryId, + @RequestParam("sourceId") Long sourceId, @RequestParam("targetId") Long targetId) { + return moduleRelationService.relevancy(relationCategoryId, sourceId, targetId); + } + + /** + * 查询模型关系记录 + * + * @param moduleId + * @param relationCategoryId + * @return + */ + @GetMapping(value = "/topo") + @Operation(tags = {"CMC", "CSC"}, summary = "根据模型ID和关联类型分组查询模型关系拓扑") + public GeneralResult list(@RequestParam("moduleId") Long moduleId, + @RequestParam("relationCategoryId") Long relationCategoryId) { + if (null == moduleId || 0 == moduleId || null == relationCategoryId || 0 == relationCategoryId) { + return ResultTools.formatErrResult(); + } else { + return moduleRelationService.list(moduleId, relationCategoryId); + } + } + + /** + * 查询模型关系记录 + * + * @param relationCategoryId + * @return + */ + @GetMapping(value = "/{relationCategoryId}/topo") + @Operation(tags = {"CMC", "CSC"}, summary = "根据关联类型分组ID查询模型拓扑") + public GeneralResult listAll(@PathVariable(value = "relationCategoryId") Long relationCategoryId) { + + if (null == relationCategoryId || 0 == relationCategoryId) { + return ResultTools.formatErrResult(); + } + + return moduleRelationService.listByCategoryId(relationCategoryId); + + } + + /** + * 查询模型关系记录 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "模型关系详情") + public GeneralResult detail(@PathVariable(value = Common.ID) Long id) { + + if (null == id || 0 == id) { + return ResultTools.formatErrResult(); + } + + return moduleRelationService.detail(id); + + } + + /** + * 新增模型关系 + * + * @param record + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC", "CSC"}, summary = "模型关系新增") + public GeneralResult save(@RequestBody ModuleRelation record, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + return moduleRelationService.create(record, context.getTarget()); + + } + + /** + * 修改模型关系 + * + * @param record + * @param context + * @return + */ + + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "模型关系修改") + public GeneralResult modify(@RequestBody ModuleRelation record, @PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + record.setId(id); + return moduleRelationService.modify(record, context.getTarget()); + + } + + /** + * 移除模型关系 + * + * @param id + * @param context + * @return + */ + + @DeleteMapping("/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "模型关系删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleRelationService.remove(id, context.getTarget()); + + } + + /** + * 关联类型分组id查询模型集合 + * + * @param relationCategoryId + * @return + */ + @GetMapping(value = "/{relationCategoryId}/module") + @Operation(tags = {"CMC", "CSC"}, summary = "关联类型分组id查询模型集合") + public GeneralResult> moduleList(@PathVariable(value = "relationCategoryId") Long relationCategoryId) { + return moduleRelationService.moduleList(relationCategoryId); + } + + private boolean paramsCheck(ModuleRelation record) { + // 参数校验 + if (null == record || null == record.getSourceId() || 0 == record.getSourceId() || null == record.getTargetId() + || 0 == record.getTargetId() || null == record.getRelationCategoryId() + || 0 == record.getRelationCategoryId() || null == record.getRelationId() || 0 == record.getRelationId()) { + return false; + } + if (StringUtils.isEmpty(record.getRule())) { + return false; + } + String type = record.getRule(); + String[] types = type.split("-"); + record.setSourceType(types[0]); + record.setTargetType(types[1]); + return true; + } + + @GetMapping(value = "/instances") + @Operation(tags = {"CMC"}, summary = "模型关系实例列表") + public GeneralResult instances(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) { + return moduleRelationService.instances(pager, context.getTarget()); + + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyController.java new file mode 100644 index 0000000..8b27e32 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyController.java @@ -0,0 +1,36 @@ +package com.bocloud.ams.booter.controller.module; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.service.module.PropertyService; +import com.megatron.common.model.GeneralResult; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/v1/property") +@Tag(name = "模型属性管理") +public class PropertyController { + + @Autowired + private PropertyService propertyService; + + /** + * 查询属性详情 + * + * @param propertyId + * @return + */ + @GetMapping(value = "/{propertyId}") + @Operation(summary = "模型属性详情") + public GeneralResult propertyDetail(@PathVariable(value = "propertyId") Long propertyId) { + return propertyService.detail(propertyId); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyPoolController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyPoolController.java new file mode 100644 index 0000000..c10e96e --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/PropertyPoolController.java @@ -0,0 +1,135 @@ +package com.bocloud.ams.booter.controller.module; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.PropertyPool; +import com.bocloud.ams.service.module.PropertyPoolService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "属性池管理") +@RestController +@RequestMapping("/v1/property/pool") +public class PropertyPoolController { + + @Autowired + private PropertyPoolService propertyPoolService; + + /** + * 查询属性池记录 + * + * @param pager + * @param context + * @return + */ + @GetMapping + @Operation(tags = {"CMC", "CSC"}, summary = "属性池列表") + public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) { + return propertyPoolService.list(pager); + } + + /** + * 新增属性池 + * + * @param record + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC", "CSC"}, summary = "属性池新增") + public GeneralResult save(@RequestBody PropertyPool record, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + return propertyPoolService.create(record, context.getTarget()); + } + + /** + * 修改属性池 + * + * @param record + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "属性池修改" ) + public GeneralResult modify(@RequestBody PropertyPool record, @PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + + record.setId(id); + return propertyPoolService.modify(record, context.getTarget()); + + } + + /** + * 移除属性池 + * + * @param id + * @param context + * @return + */ + @DeleteMapping("/{id}") + @Operation(tags = {"CMC", "CSC"}, summary = "属性池删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return propertyPoolService.remove(id, context.getTarget()); + + } + + private boolean paramsCheck(PropertyPool record) { + // 参数校验 + if (null == record || StringUtils.isEmpty(record.getName()) || StringUtils.isEmpty(record.getCode()) + || StringUtils.isEmpty(record.getType())) { + return false; + } + // 下拉选择类型中,属性池配置项必须有值 + if (PropertyConstant.PropertyType.SINGLESELECT.equals(record.getType()) + || PropertyConstant.PropertyType.MULTISELECT.equals(record.getType()) + || PropertyConstant.PropertyType.RADIO.equals(record.getType()) + || PropertyConstant.PropertyType.CHECKBOX.equals(record.getType())) { + if (CollectionUtils.isEmpty(record.getItemList())) { + return false; + } + } + + if (PropertyConstant.PropertyType.MULTILINETABLE.equals(record.getType()) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(record.getType())) { + + if (PropertyConstant.TABLE_TYPE_ONE.equals(record.getTableType())) { + if (null == record.getLinkModuleId() || 0 == record.getLinkModuleId() + || StringUtils.isEmpty(record.getPropertyIds())) { + return false; + } + } else { + if (CollectionUtils.isEmpty(record.getItemList())) { + return false; + } + } + } + return true; + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RegularExpressionController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RegularExpressionController.java new file mode 100644 index 0000000..b2e6a56 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RegularExpressionController.java @@ -0,0 +1,37 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.RegularExpression; +import com.bocloud.ams.service.module.RegularExpressionService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "正则表达式管理") +@RestController +@RequestMapping("/v1/regexps") +public class RegularExpressionController { + + @Autowired + private RegularExpressionService regularExpressionService; + + /** + * 查询所有的正则表达式 + * + * @return + */ + @GetMapping + @Operation(tags = {"CMC"}, summary ="正则表达式列表") + public GeneralResult> list(@RequestParam(value = Common.TYPE) String type) { + return regularExpressionService.list(type); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationCategoryController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationCategoryController.java new file mode 100644 index 0000000..e09820e --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationCategoryController.java @@ -0,0 +1,132 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.service.module.RelationCategoryService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "关联类型分组管理") +@RestController +@RequestMapping("/v1/relation/category") +public class RelationCategoryController { + + @Autowired + private RelationCategoryService relationCategoryService; + + /** + * 查询关联类型分组记录 + * + * @param pager + * @return + */ + @GetMapping + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型分组列表") + public GeneralResult> list(Pager pager) { + return relationCategoryService.list(pager); + } + + @GetMapping("/all") + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型分组列表(所有)") + public GeneralResult> listAll(Pager pager) { + return relationCategoryService.listAll(pager.getParams(), pager.getSorter()); + } + + /** + * 新增关联类型分组 + * + * @param record + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型分组新增") + public GeneralResult save(@RequestBody RelationCategory record, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + try { + return relationCategoryService.create(record, context.getTarget()); + } catch (Exception e) { + return new GeneralResult<>(false, "关联类型分组新增失败"); + } + } + + /** + * 修改关联类型分组 + * + * @param record + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型分组修改") + public GeneralResult modify(@RequestBody RelationCategory record, @PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + record.setId(id); + + return relationCategoryService.modify(record, context.getTarget()); + } + + /** + * 移除关联类型分组 + * + * @param id + * @param context + * @return + */ + @DeleteMapping("/{id}") + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型分组删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + try { + return relationCategoryService.remove(id, context.getTarget()); + } catch (Exception e) { + return new GeneralResult<>(false, "关联类型分组删除失败"); + } + } + + private boolean paramsCheck(RelationCategory record) { + // 参数校验 + if (null == record || StringUtils.isEmpty(record.getName()) || StringUtils.isEmpty(record.getCode())) { + return false; + } + return true; + } + + @GetMapping(value = "/{id}/module/relations") + @Operation(tags = {"CMC"}, summary ="关联类型分组模型关系查询") + public GeneralResult> moduleRelationList(@PathVariable(value = Common.ID) Long id, + @RequestParam(value = "moduleId") Long moduleId) { + return relationCategoryService.moduleRelationList(id, moduleId); + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationController.java new file mode 100644 index 0000000..fc53460 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/RelationController.java @@ -0,0 +1,105 @@ +package com.bocloud.ams.booter.controller.module; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.module.Relation; +import com.bocloud.ams.service.module.RelationService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "关联类型管理") +@RestController +@RequestMapping("/v1/relation") +public class RelationController { + + @Autowired + private RelationService relationService; + + /** + * 查询关联类型记录 + * + * @param pager + * @param context + * @return + */ + @GetMapping + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型列表") + public GeneralResult> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) { + return relationService.list(pager); + } + + /** + * 新增关联类型 + * + * @param record + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型新增") + public GeneralResult save(@RequestBody Relation record, @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + return relationService.create(record, context.getTarget()); + } + + /** + * 修改关联类型 + * + * @param record + * @param context + * @return + */ + @PutMapping(value = "/{id}") + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型修改") + public GeneralResult modify(@RequestBody Relation record, @PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + + if (!paramsCheck(record)) { + return new GeneralResult<>(false, "参数异常"); + } + record.setId(id); + return relationService.modify(record, context.getTarget()); + } + + /** + * 移除关联类型 + * + * @param id + * @param context + * @return + */ + @DeleteMapping("/{id}") + @Operation(tags = {"CMC", "CSC"}, summary ="关联类型删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return relationService.remove(id, context.getTarget()); + } + + private boolean paramsCheck(Relation record) { + // 参数校验 + if (null == record || StringUtils.isEmpty(record.getName()) || StringUtils.isEmpty(record.getCode()) + || null == record.getCategoryId() || 0L == record.getCategoryId()) { + return false; + } + return true; + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/TopologyConfigController.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/TopologyConfigController.java new file mode 100644 index 0000000..576ca3b --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/controller/module/TopologyConfigController.java @@ -0,0 +1,237 @@ +package com.bocloud.ams.booter.controller.module; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +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 org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.bocloud.ams.entity.model.ColumnAndSearchItemModel; +import com.bocloud.ams.entity.model.InstanceTopo; +import com.bocloud.ams.entity.model.PathModel; +import com.bocloud.ams.entity.model.ResponseInstanceTopologyModel; +import com.bocloud.ams.entity.module.TopologyConfig; +import com.bocloud.ams.service.module.TopologyConfigService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; + +@Tag(name = "实例拓扑管理") +@RestController +@RequestMapping("/v1/instance/topology") +public class TopologyConfigController { + + @Autowired + private TopologyConfigService topologyConfigService; + + /** + * 拓扑实例列表 + * + * @param pager + * @param context + * @return + */ + @GetMapping + @Operation(tags = {"CMC", "CSC"}, summary ="实例拓扑列表") + public GeneralResult> list(Pager pager, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return topologyConfigService.list(pager); + } + + /** + * 新增模型 + * + * @param config + * @param context + * @return + */ + @PostMapping + @Operation(tags = {"CMC"}, summary ="实例拓扑新增") + public GeneralResult save(@RequestBody TopologyConfig config, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return topologyConfigService.save(config, context.getTarget()); + } + + /** + * 更新实例图谱 + * + * @param config + * @param context + * @return + */ + @PutMapping + @Operation(tags = {"CMC"}, summary ="实例拓扑修改") + public GeneralResult modify(@RequestBody TopologyConfig config, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return topologyConfigService.modify(config, context.getTarget()); + } + + /** + * 删除拓扑实例 + * + * @param id + * @param context + * @return + */ + + @DeleteMapping("/{id}") + @Operation(tags = {"CMC", "CSC"}, summary ="拓扑实例删除") + public GeneralResult remove(@PathVariable(value = Common.ID) Long id, + @Value(Common.REQ_CONTEXT) RequestContext context) { + return topologyConfigService.remove(id, context.getTarget()); + } + + /** + * 查询实例拓扑详情 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}") + @Operation(summary = "实例拓扑详情") + public GeneralResult detail(@PathVariable(value = "id") Long id) { + return topologyConfigService.detail(id); + } + + /** + * 根据起始模型查询最大拓扑层级 + * + * @param categoryId + * @param startModuleId + * @return + */ + @GetMapping(value = "/max/level") + @Operation(summary = "根据起始模型查询最大拓扑层级") + public GeneralResult maxLevel(@RequestParam("categoryId") Long categoryId, + @RequestParam("startModuleId") Long startModuleId) { + return topologyConfigService.maxLevel(categoryId, startModuleId); + } + + /** + * 获取拓扑路径 + * + * @param categoryId + * @param startModuleId + * @param topologyLevel + * @param ignoreModuleId + * @param wayModuleId + * @return + */ + @GetMapping(value = "/path") + @Operation(summary = "获取拓扑路径") + public GeneralResult> topologyPath(@RequestParam("categoryId") Long categoryId, + @RequestParam("startModuleId") Long startModuleId, @RequestParam("topologyLevel") Integer topologyLevel, + @RequestParam(value = "ignoreModuleId", required = false) String ignoreModuleId, + @RequestParam(value = "wayModuleId", required = false) String wayModuleId) { + return topologyConfigService.topologyPath(categoryId, startModuleId, topologyLevel, ignoreModuleId, + wayModuleId); + } + + /** + * 获取查询项以及列表项 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}/dynamic/item") + @Operation(summary = "获取查询项以及列表项") + public GeneralResult searchItemList(@PathVariable(value = "id") Long id) { + return topologyConfigService.searchItemList(id); + } + + /** + * 查询资源列表 + * + * @param pager + * @return + */ + @GetMapping(value = "/resource") + @Operation(summary = "查询资源列表") + public GeneralResult>> resourcelist(Pager pager) { + return topologyConfigService.resourcelist(pager); + } + + /** + * 根据实例拓扑id查询对应起始模型的实例集合 + * + * @param id + * @return + */ + @GetMapping(value = "/{id}/startmodule/instance") + @Operation(summary = "根据实例拓扑id查询对应起始模型的实例集合") + public GeneralResult> + startModuleInstanceList(@PathVariable(value = "id") Long id) { + return topologyConfigService.startModuleInstanceList(id); + } + + /** + * 实例拓扑-资源列表导出 + * + * @param id + * @param response + * @return + */ + @GetMapping("/{id}/export") + @Operation(summary = "实例拓扑资源列表导出") + public GeneralResult download(@PathVariable Long id, HttpServletResponse response) { + return topologyConfigService.download(id, response); + } + + /** + * 实例拓扑-全局拓扑 + * + * @param id + * @param instanceId + * @return + */ + @GetMapping(value = "/topo") + @Operation(summary = "全局拓扑") + public GeneralResult topoList(@RequestParam(value = "id") Long id, + @RequestParam(value = "instanceId") Long instanceId) { + return topologyConfigService.topoList(id, instanceId); + } + + /** + * 实例资源拓扑 + * + * @param id + * @param instanceId + * @return + */ + @GetMapping(value = "/topo/instances/{instanceId}") + @Operation(summary = "实例资源拓扑") + public GeneralResult topology(@RequestParam(value = "id") Long id, + @PathVariable Long instanceId) { + return topologyConfigService.topology(id, instanceId); + } + + /** + * 实例拓扑-根据实例id查找下一层级实例拓扑 + * + * @param id + * @param instanceId + * @return + */ + @GetMapping(value = "/next/topo") + @Operation(summary = "根据实例id查找下一层级实例拓扑") + public GeneralResult nextTopoList(@RequestParam(value = "id") Long id, + @RequestParam(value = "moduleId") Long moduleId, @RequestParam(value = "instanceId") Long instanceId) { + return topologyConfigService.nextTopoList(id, moduleId, instanceId); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/listener/TaskResultListener.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/listener/TaskResultListener.java new file mode 100644 index 0000000..7d81a60 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/listener/TaskResultListener.java @@ -0,0 +1,93 @@ +package com.bocloud.ams.booter.listener; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.enums.CollectionEnum; +import com.bocloud.ams.entity.enums.Status; +import com.bocloud.ams.entity.model.TaskInstanceBean; +import com.bocloud.ams.service.collection.CollectionTaskInstanceService; +import com.bocloud.ams.service.utils.CollectionHistoryHelper; +import com.bocloud.ams.task.model.JobResult; +import com.megatron.common.model.GeneralResult; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.Charset; +import java.util.Date; + +/** + * @Author liuyuanyuan + * @Date 2022/6/14 0014 18:31 + * @Description:采集任务结果监听 + */ +@Slf4j +@Component("taskResultListener") +public class TaskResultListener implements MessageListener { + @Autowired + private CollectionTaskInstanceService cmdbCollectionTaskInstanceService; + @Autowired + private CollectionHistoryHelper historyHelper; + + private void processDebugLog(String format, Object... objects) { + if (log.isDebugEnabled()) { + log.debug(format, objects); + } + } + + @Override + public void onMessage(Message message) { + try { + String content = new String(message.getBody(), Charset.forName("UTF-8")); + processDebugLog("get bocloud message:{}", content); + if (StringUtils.isBlank(content)) { + // 消息没有内容,直接确认收到 淹没处理 + return; + } + JobResult jobResult = JSONObject.parseObject(content, JobResult.class); + if (null == jobResult) { + // 消息参数格式错误,直接确认收到淹没处理 + return; + } + log.info("收到任务执行消息{}", content); + //查询任务数据 + GeneralResult instanceResult = cmdbCollectionTaskInstanceService.queryByTaskId(jobResult.getJob().getTaskId()); + if (instanceResult.isFailed()) { + log.info("任务数据不存在,taskId{}", jobResult.getJob().getTaskId()); + return; + } + CollectionTaskInstance instance = instanceResult.getData(); + TaskInstanceBean instanceBean = new TaskInstanceBean(); + instanceBean.setOutput(jobResult.getMsg()); + instanceBean.setId(instance.getId()); + instanceBean.setGmtModify(new Date()); + instanceBean.setCollectionFinish(new Date()); + BigDecimal start = new BigDecimal(instance.getGmtStart().getTime()); + BigDecimal end = new BigDecimal(instanceBean.getCollectionFinish().getTime()); + instanceBean.setCollectionTime(Math.abs(end.subtract(start).divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP).doubleValue())); + if (jobResult.isSuccess()) { + instanceBean.setStatus(Status.Inst.RUNNING.name()); + instanceBean.setCollectionStatus(Status.Inst.SUCCESS.name()); + } else { + instanceBean.setCollectionStatus(Status.Inst.FAILED.name()); + instanceBean.setStatus(CollectionEnum.Status.ERROR.name()); + instanceBean.setGmtFinish(new Date()); + } + cmdbCollectionTaskInstanceService.modify(instanceBean, instance.getCreatorId()); + log.info("采集任务:{}已完成!开始时间:{},结束时间:{},总耗时:{}", jobResult.getJob().getTaskId(), start, end, instanceBean.getCollectionTime()); + if (jobResult.isSuccess()) { + GeneralResult result = historyHelper.history(instance.getId(), instance.getCode(), jobResult.getMsg(), instance.getCreatorId()); + if (result.isFailed()) { + cmdbCollectionTaskInstanceService.updateStatus(instance.getId(), CollectionEnum.Status.ERROR.name()); + } + } + } catch (Exception e) { + log.error("Get error message:{}", e.getMessage()); + } + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/CollectionTaskInstanceBakScheduler.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/CollectionTaskInstanceBakScheduler.java new file mode 100644 index 0000000..b0f99df --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/CollectionTaskInstanceBakScheduler.java @@ -0,0 +1,373 @@ +package com.bocloud.ams.booter.scheduler; + +import com.bocloud.ams.entity.TableLog; +import com.bocloud.ams.entity.collection.CollectionHistory; +import com.bocloud.ams.entity.collection.CollectionHistoryBak; +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.bocloud.ams.entity.collection.CollectionHistoryItemBak; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.collection.CollectionTaskInstanceBak; +import com.bocloud.ams.entity.config.CmdbConfig; +import com.bocloud.ams.entity.enums.Status; +import com.bocloud.ams.repository.TableLogRepository; +import com.bocloud.ams.repository.collection.CollectionHistoryBakRepository; +import com.bocloud.ams.repository.collection.CollectionHistoryItemBakRepository; +import com.bocloud.ams.repository.collection.CollectionHistoryItemRepository; +import com.bocloud.ams.repository.collection.CollectionHistoryRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceBakRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceRepository; +import com.bocloud.ams.repository.config.CmdbConfigRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.google.common.collect.Lists; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Param; +import com.megatron.common.model.Sign; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.core.CurrentService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author huliwei + * @date 2023/4/24 + */ + +@Slf4j +@Component +public class CollectionTaskInstanceBakScheduler { + + private static final String CMDB_COLLECTION_TASK_INSTANCE_BAK_ = "ci_collection_task_instance_bak_"; + private static final String CMDB_COLLECTION_HISTORY_BAK_ = "ci_collection_history_bak_"; + private static final String CMDB_COLLECTION_HISTORY_ITEM_BAK_ = "ci_collection_history_item_bak_"; + + private static final String CMDB_COLLECTION_TASK_INSTANCE_BAK = "ci_collection_task_instance_bak"; + private static final String CMDB_COLLECTION_HISTORY_BAK = "ci_collection_history_bak"; + private static final String CMDB_COLLECTION_HISTORY_ITEM_BAK = "ci_collection_history_item_bak"; + + @Autowired + private CurrentService service; + @Autowired + private CollectionTaskInstanceRepository collectionTaskInstanceRepository; + @Autowired + private CollectionHistoryRepository collectionHistoryRepository; + @Autowired + private CollectionHistoryItemRepository collectionHistoryItemRepository; + @Autowired + private CmdbConfigRepository cmdbConfigRepository; + @Autowired + private TableLogRepository tableLogRepository; + @Autowired + private CollectionTaskInstanceBakRepository collectionTaskInstanceBakRepository; + @Autowired + private CollectionHistoryBakRepository collectionHistoryBakRepository; + @Autowired + private CollectionHistoryItemBakRepository collectionHistoryItemBakRepository; + + + //每月第一天的0时1分开始创建当月的备份表 + @Scheduled(cron = "${collection.task.instance.create-table:0 1 0 1 * ? }") + private void createTable() { + try { + //ci_collection_history_bak_202304 + String tableNameTaskInstanceBak = CMDB_COLLECTION_TASK_INSTANCE_BAK_ + this.getTableSuffix(LocalDateTime.now()); + String tableNameHistoryBak = CMDB_COLLECTION_HISTORY_BAK_ + this.getTableSuffix(LocalDateTime.now()); + String tableNameHistoryItemBak = CMDB_COLLECTION_HISTORY_ITEM_BAK_ + this.getTableSuffix(LocalDateTime.now()); + this.createCollectionTaskInstanceBakTable(tableNameTaskInstanceBak); + this.createCollectionHistoryBakTable(tableNameHistoryBak); + this.createCollectionHistoryItemBakTable(tableNameHistoryItemBak); + } catch (Exception e) { + log.error("定时创建库表失败", e); + return; + } + } + + @Scheduled(cron = "${collection.task.instance.bakup:0 0 4 * * ?}") + private void instanceDataBak() { + if (!service.isLeader()) { + return; + } + log.info("开始备份任务数据"); + List instances = null; + int stepSize = 200; + try { + CmdbConfig switchConfig = cmdbConfigRepository.queryByCode("CmdbCollectionTaskInstanceDataBakSwitch"); + if (null == switchConfig || StringUtils.isEmpty(switchConfig.getValue()) || !switchConfig.getValue().equalsIgnoreCase("true")) { + log.info("备份任务未开启"); + return; + } + Integer days = null; + CmdbConfig config = cmdbConfigRepository.queryByCode("CmdbCollectionTaskInstanceDataBakDaysAgo"); + if (null != config && StringUtils.isNotEmpty(config.getValue())) { + days = Integer.valueOf(config.getValue()); + } + days = null == days ? 90 : days; + LocalDate localDate = LocalDate.now().minusDays(days); + LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String formatTime = dateTimeFormatter.format(localDateTime); + log.info("备份{}之前的数据", formatTime); + List params = Lists.newArrayList(); + params.add(new Param(MapTools.simpleMap("gmtCreate", formatTime), Sign.LET)); + instances = this.collectionTaskInstanceRepository.list(params); + } catch (Exception e) { + log.error("查询任务实例失败", e); + return; + } + if (ListTool.isEmpty(instances)) { + log.info("结束备份任务数据,没有查询到需要备份的数据"); + return; + } + int size = instances.size(); + log.info("备份任务数{},每批任务数{}", size, stepSize); + if (size > stepSize) { + int num = size % stepSize == 0 ? size / stepSize : size / stepSize + 1; + for (int i = 0; i < num; i++) { + log.info("备份第{}批数据", i + 1); + if (i + 1 == num) { + batchBak(instances.subList(i * stepSize, size)); + } else { + batchBak(instances.subList(i * stepSize, (i + 1) * stepSize)); + } + } + + } else { + batchBak(instances); + } + log.info("结束备份任务数据"); + } + + private void batchBak(List instances) { + try { + //根据年和月分组 + Map> map = new HashMap<>(); + for (CollectionTaskInstance instance : instances) { + LocalDateTime localDateTime = LocalDateTime.ofInstant(instance.getGmtCreate().toInstant(), ZoneId.systemDefault()); + String tableSuffix = this.getTableSuffix(localDateTime); + if (map.containsKey(tableSuffix)) { + List taskInstanceList = map.get(tableSuffix); + taskInstanceList.add(instance); + } else { + List taskInstances = new ArrayList<>(); + taskInstances.add(instance); + map.put(tableSuffix, taskInstances); + } + } + for (String tableSuffix : map.keySet()) { + //备份ci_collection_task_instance + List taskInstances = map.get(tableSuffix); + List instanceIds = taskInstances.stream().map(CollectionTaskInstance::getId).collect(Collectors.toList()); + List instanceBaks = Lists.newArrayList(); + for (CollectionTaskInstance instance : instances) { + CollectionTaskInstanceBak bak = new CollectionTaskInstanceBak(); + BeanUtils.copyProperties(instance, bak); + instanceBaks.add(bak); + } + if (!instanceBaks.isEmpty()) { + String tableName = CMDB_COLLECTION_TASK_INSTANCE_BAK_ + tableSuffix; + GeneralResult taskInstanceBakTable = this.createCollectionTaskInstanceBakTable(tableName); + if (taskInstanceBakTable.isSuccess()) { + this.batchSaveCollectionTaskInstanceBak(instanceBaks, tableName); + collectionTaskInstanceRepository.delete(instanceIds); + } + } + //备份ci_collection_history + List collectionHistories = collectionHistoryRepository.listByInstances(instanceIds); + List historyIds = collectionHistories.stream().map(CollectionHistory::getId).collect(Collectors.toList()); + List collectionHistoryBaks = Lists.newArrayList(); + for (CollectionHistory collectionHistory : collectionHistories) { + CollectionHistoryBak collectionHistoryBak = new CollectionHistoryBak(); + BeanUtils.copyProperties(collectionHistory, collectionHistoryBak); + collectionHistoryBaks.add(collectionHistoryBak); + } + if (!collectionHistoryBaks.isEmpty()) { + String tableName = CMDB_COLLECTION_HISTORY_BAK_ + tableSuffix; + GeneralResult collectionHistoryBakTable = this.createCollectionHistoryBakTable(tableName); + if (collectionHistoryBakTable.isSuccess()) { + this.batchSaveCollectionHistoryBak(collectionHistoryBaks, tableName); + collectionHistoryRepository.deleteByInstanceIds(instanceIds); + } + } + //备份ci_collection_history_item + if (!ListTool.isEmpty(historyIds)) { + List collectionHistoryItems = collectionHistoryItemRepository.listByHistoryIds(historyIds); + List collectionHistoryItemBaks = Lists.newArrayList(); + for (CollectionHistoryItem relation : collectionHistoryItems) { + CollectionHistoryItemBak collectionHistoryItemBak = new CollectionHistoryItemBak(); + BeanUtils.copyProperties(relation, collectionHistoryItemBak); + collectionHistoryItemBaks.add(collectionHistoryItemBak); + } + if (!collectionHistoryItemBaks.isEmpty()) { + String tableName = CMDB_COLLECTION_HISTORY_ITEM_BAK_ + tableSuffix; + GeneralResult collectionHistoryItemBakTable = this.createCollectionHistoryItemBakTable(tableName); + if (collectionHistoryItemBakTable.isSuccess()) { + this.batchSaveCollectionHistoryItemBak(collectionHistoryItemBaks, tableName); + collectionHistoryItemRepository.deleteByHistoryIds(historyIds); + } + } + } + } + } catch (Exception e) { + log.error("任务备份异常", e); + } + } + + /** + * 批量保存 + * + * @param collectionTaskInstanceBaks 需要保存的数据 + * @param tableName 备份表名称 + */ + private void batchSaveCollectionTaskInstanceBak(List collectionTaskInstanceBaks, String tableName) { + synchronized (CollectionTaskInstanceBak.class) { + CmdbUtils.changeTableAnnotationValue(CollectionTaskInstanceBak.class, tableName); + collectionTaskInstanceBakRepository.batchSave(collectionTaskInstanceBaks, collectionTaskInstanceBaks.size(), false); + //还原操作 + CmdbUtils.changeTableAnnotationValue(CollectionTaskInstanceBak.class, CMDB_COLLECTION_TASK_INSTANCE_BAK); + } + } + + /** + * 批量保存 + * + * @param collectionHistoryBaks 需要保存的数据 + * @param tableName 备份表名称 + */ + private void batchSaveCollectionHistoryBak(List collectionHistoryBaks, String tableName) { + synchronized (CollectionHistoryBak.class) { + CmdbUtils.changeTableAnnotationValue(CollectionHistoryBak.class, tableName); + collectionHistoryBakRepository.batchSave(collectionHistoryBaks, collectionHistoryBaks.size(), false); + //还原操作 + CmdbUtils.changeTableAnnotationValue(CollectionHistoryBak.class, CMDB_COLLECTION_HISTORY_BAK); + } + } + + /** + * 批量保存 + * + * @param collectionHistoryItemBaks 需要保存的数据 + * @param tableName 备份表名称 + */ + private void batchSaveCollectionHistoryItemBak(List collectionHistoryItemBaks, String tableName) { + synchronized (CollectionHistoryItemBak.class) { + CmdbUtils.changeTableAnnotationValue(CollectionHistoryItemBak.class, tableName); + collectionHistoryItemBakRepository.batchSave(collectionHistoryItemBaks, collectionHistoryItemBaks.size(), false); + //还原操作 + CmdbUtils.changeTableAnnotationValue(CollectionHistoryItemBak.class, CMDB_COLLECTION_HISTORY_ITEM_BAK); + } + + } + + /** + * 动态创建表 + * + * @param tableName 需要创建的表名称 + * @return + */ + private GeneralResult createCollectionTaskInstanceBakTable(String tableName) { + synchronized (CollectionTaskInstanceBak.class) { + String templateTable = CMDB_COLLECTION_TASK_INSTANCE_BAK; + try { + if (collectionTaskInstanceBakRepository.countTable(tableName) <= 0) { + collectionTaskInstanceBakRepository.createTable(tableName, new CollectionTaskInstanceBak()); + this.saveTableLog(tableName, templateTable, Status.Inst.SUCCESS.name()); + } + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + this.saveTableLog(tableName, templateTable, Status.Inst.FAILED.name()); + log.error("create ci_collection_task_instance_bak table error:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + } + + /** + * 动态创建表 + * + * @param tableName 需要创建的表名称 + * @return + */ + private GeneralResult createCollectionHistoryBakTable(String tableName) { + synchronized (CollectionHistoryBak.class) { + String templateTable = CMDB_COLLECTION_HISTORY_BAK; + try { + if (collectionHistoryBakRepository.countTable(tableName) <= 0) { + collectionHistoryBakRepository.createTable(tableName, new CollectionHistoryBak()); + this.saveTableLog(tableName, templateTable, Status.Inst.SUCCESS.name()); + } + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + this.saveTableLog(tableName, templateTable, Status.Inst.FAILED.name()); + log.error("create ci_collection_history_bak table error:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + } + + /** + * 动态创建表 + * + * @param tableName 需要创建的表名称 + * @return + */ + private GeneralResult createCollectionHistoryItemBakTable(String tableName) { + synchronized (CollectionHistoryItemBak.class) { + String templateTable = CMDB_COLLECTION_HISTORY_ITEM_BAK; + try { + if (collectionHistoryItemBakRepository.countTable(tableName) <= 0) { + collectionHistoryItemBakRepository.createTable(tableName, new CollectionHistoryItemBak()); + this.saveTableLog(tableName, templateTable, Status.Inst.SUCCESS.name()); + } + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + this.saveTableLog(tableName, templateTable, Status.Inst.FAILED.name()); + log.error("create ci_collection_history_item_bak table error:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + } + + private void saveTableLog(String tableName, String templateTableName, String status) { + TableLog tableLog = new TableLog(); + tableLog.setName(tableName); + tableLog.setCode("BACKUP"); + tableLog.setStatus(status); + tableLog.setTemplateTable(templateTableName); + tableLog.setGmtCreate(new Date()); + tableLog.setDeleted(false); + tableLogRepository.save(tableLog); + } + + /** + * 获取动态表的后缀 + * + * @param localDate + * @return + */ + private String getTableSuffix(LocalDateTime localDate) { + //2023 + int year = localDate.getYear(); + //4 + int month = localDate.getMonth().getValue(); + String months = String.valueOf(month).length() > 1 ? String.valueOf(month) : "0" + month; + //202304 + String suffix = year + months; + return suffix; + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/ModuleInstanceRelationScheduler.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/ModuleInstanceRelationScheduler.java new file mode 100644 index 0000000..bdf44ec --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/ModuleInstanceRelationScheduler.java @@ -0,0 +1,50 @@ +package com.bocloud.ams.booter.scheduler; + +import java.util.concurrent.TimeUnit; + +import com.megatron.framework.core.CurrentService; +import com.megatron.framework.lock.AutoCloseLock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Description: 模型实例关系定时任务 + * @Title: ModuleInstanceRelationScheduler + * @Author: majiali + * @CreateTime: 2022/6/9 15:53 + */ +@Slf4j +@Component +public class ModuleInstanceRelationScheduler { + + @Autowired + private InstanceAutoRelationService instanceAutoRelationService; + @Autowired + private CurrentService service; + @Autowired + private LockFactory lockFactory; + + @Scheduled(cron = "${module.instance.relation.schedule:0 0 2 * * ?}") // 每天凌晨两点执行 + private void autoRelation() { + if (!service.isLeader()) { + log.info("当前服务不是主服务,不执行定时任务"); + return; + } + log.info("开始定时处理模型实例关系"); + String path = ModuleInstanceRelationScheduler.class.getSimpleName() + "_autoRelation"; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + instanceAutoRelationService.autoRelation(); + } catch (Exception e) { + log.error("Auto relation scheduler fail:", e); + } + log.info("结束定时处理模型实例关系"); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/OperationalAuditBakScheduler.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/OperationalAuditBakScheduler.java new file mode 100644 index 0000000..07373a7 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/scheduler/OperationalAuditBakScheduler.java @@ -0,0 +1,231 @@ +package com.bocloud.ams.booter.scheduler; + + +import com.alibaba.excel.util.DateUtils; +import com.bocloud.ams.entity.config.CmdbConfig; +import com.bocloud.ams.entity.TableLog; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.audit.OperationalAuditBak; +import com.bocloud.ams.entity.enums.Status; +import com.bocloud.ams.repository.config.CmdbConfigRepository; +import com.bocloud.ams.repository.TableLogRepository; +import com.bocloud.ams.repository.audit.OperationalAuditBakRepository; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.google.common.collect.Lists; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Param; +import com.megatron.common.model.Sign; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.core.CurrentService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class OperationalAuditBakScheduler { + + @Autowired + private CurrentService service; + @Autowired + private OperationalAuditRepository operationalAuditRepository; + + + @Autowired + private OperationalAuditBakRepository operationalAuditBakRepository; + @Autowired + private TableLogRepository tableLogRepository; + + @Autowired + private CmdbConfigRepository cmdbConfigRepository; + + //每月第一天的0时1分开始创建当月的备份表 + @Scheduled(cron = "${operational.audit.create-table:0 1 0 1 * ? }") + private void createTable() { + try { + if (!service.isLeader()) { + return; + } + CmdbConfig switchConfig = cmdbConfigRepository.queryByCode("CmdbOperationalAuditDataBakSwitch"); + if (null == switchConfig || StringUtils.isEmpty(switchConfig.getValue()) || !switchConfig.getValue().equalsIgnoreCase("true")) { + log.info("备份操作审计未开启"); + return; + } + String time = DateUtils.format(new Date(), "yyyyMM"); + //ci_operational_audit_bak_202304 + String tableNameTaskNodeBak = CmdbUtils.CMDB_OPERATIONAL_AUDIT_BAK + time; + createOperationalAuditBakTable(tableNameTaskNodeBak); + } catch (Exception e) { + log.error("定时创建库表失败", e); + } + } + + private GeneralResult createOperationalAuditBakTable(String tableName) { + String status = Status.Inst.SUCCESS.name(); + try { + if (operationalAuditBakRepository.countTable(tableName) > 0) { + log.warn("创建表空间{}失败,表空间已经存在", tableName); + return new GeneralResult<>(false, "创建失败"); + } + operationalAuditBakRepository.createTable(tableName, new OperationalAuditBak()); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + status = Status.Inst.FAILED.name(); + log.error("create OperationalAuditBak table error:", e); + return new GeneralResult<>(false, "创建失败"); + } finally { + TableLog tableLog = new TableLog(); + tableLog.setCode("BACKUP"); + tableLog.setStatus(status); + tableLog.setName(tableName); + tableLog.setTemplateTable(CmdbUtils.CMDB_OPERATIONAL_AUDIT_BAK); + tableLog.setGmtCreate(new Date()); + tableLog.setDeleted(false); + tableLogRepository.save(tableLog); + } + } + + @Scheduled(cron = "${operational.audit.bakup:0 0 4 * * ?}") + public void operationalAuditDataBak() { + if (!service.isLeader()) { + return; + } + log.info("开始备份操作审计数据"); + List instances = null; + List params = Lists.newArrayList(); + try { + CmdbConfig switchConfig = cmdbConfigRepository.queryByCode("CmdbOperationalAuditDataBakSwitch"); + if (null == switchConfig || StringUtils.isEmpty(switchConfig.getValue()) || !switchConfig.getValue().equalsIgnoreCase("true")) { + log.info("备份操作审计未开启"); + return; + } + Integer days = 90; + CmdbConfig config = cmdbConfigRepository.queryByCode("CmdbOperationalAuditDataBakDaysAgo"); + if (null != config && StringUtils.isNotEmpty(config.getValue())) { + days = Integer.valueOf(config.getValue()); + } + days = null == days ? 90 : days; + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, -days); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String time = formatter.format(calendar.getTime()); + log.info("备份{}之前的数据", time); + params.add(new Param(MapTools.simpleMap("gmtCreate", time), Sign.LT)); + //查询备份数据的备份表后缀 + instances = this.operationalAuditRepository.listTime(params); + + } catch (Exception e) { + log.error("查询操作审计失败", e); + return; + } + if (ListTool.isEmpty(instances)) { + log.info("结束备份操作审计数据,没有查询到需要备份的数据"); + return; + } + //按照时间分组 + Map> map = new HashMap<>(); + for (OperationalAudit audit : instances) { + String key = audit.getDateStr().replace("-", ""); + String tableName = CmdbUtils.CMDB_OPERATIONAL_AUDIT_BAK + key; + GeneralResult result = chargeTableExist(tableName); + if (result.isSuccess()) { + batchesBak(audit.getDateStr(), tableName,params); + } + } + + log.info("结束备份操作审计数据"); + } + + private GeneralResult chargeTableExist(String tableName) { + String status = Status.Inst.SUCCESS.name(); + try { + if (operationalAuditBakRepository.countTable(tableName) > 0) { + return new GeneralResult<>(true, "表已经存在"); + } + operationalAuditBakRepository.createTable(tableName, new OperationalAuditBak()); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + status = Status.Inst.FAILED.name(); + log.error("create OperationalAuditBak table error:", e); + return new GeneralResult<>(false, "创建失败"); + } finally { + TableLog tableLog = new TableLog(); + tableLog.setCode("BACKUP"); + tableLog.setName(tableName); + tableLog.setStatus(status); + tableLog.setTemplateTable("ci_operational_audit"); + tableLog.setGmtCreate(new Date()); + tableLog.setDeleted(false); + tableLogRepository.save(tableLog); + } + } + + private void batchesBak(String dateStr, String tableName,List params) { + try { + List newParams = Lists.newArrayList(); + newParams.addAll(params); + newParams.add(new Param(MapTools.simpleMap("dateStr", dateStr), Sign.LK)); + while (true) { + List instances = operationalAuditRepository.list(newParams, 1000); + if (ListTool.isEmpty(instances)) { + log.info("结束备份任务数据,没有查询到需要备份的数据"); + break; + } + int stepSize = 100; + int size = instances.size(); + log.info("备份操作审计数{},每批操作审计数{}", size, stepSize); + if (size > stepSize) { + int num = size % stepSize == 0 ? size / stepSize : size / stepSize + 1; + for (int i = 0; i < num; i++) { + log.info("备份第{}批数据", i + 1); + if (i + 1 == num) { + batchBak(instances.subList(i * stepSize, size), tableName); + } else { + batchBak(instances.subList(i * stepSize, (i + 1) * stepSize), tableName); + } + } + + } else { + batchBak(instances, tableName); + } + } + + } catch (Exception e) { + log.error("备份操作审计异常", e); + } + } + + private void batchBak(List instances, String tableName) { + try { + List ids = instances.stream().map(OperationalAudit::getId).collect(Collectors.toList()); + List instanceBaks = Lists.newArrayList(); + for (OperationalAudit instance : instances) { + OperationalAuditBak bak = new OperationalAuditBak(); + BeanUtils.copyProperties(instance, bak); + instanceBaks.add(bak); + } + if (!instanceBaks.isEmpty()) { + operationalAuditBakRepository.batchSaveOperationalAuditBak(instanceBaks, tableName, instanceBaks.size()); + } + //删除原表数据 + operationalAuditRepository.delete(ids); + + } catch (Exception e) { + log.error("操作审计备份异常", e); + } + } + +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogAppenderTcpAndUdp.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogAppenderTcpAndUdp.java new file mode 100644 index 0000000..261c8be --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogAppenderTcpAndUdp.java @@ -0,0 +1,15 @@ +package com.bocloud.ams.booter.syslog; + +import ch.qos.logback.classic.net.SyslogAppender; +import ch.qos.logback.core.net.SyslogOutputStream; + +import java.net.SocketException; +import java.net.UnknownHostException; + +public class SysLogAppenderTcpAndUdp extends SyslogAppender { + + @Override + public SyslogOutputStream createOutputStream() throws SocketException, UnknownHostException { + return new SyslogOutputStreamTcpAndUdp(getSyslogHost(), getPort()); + } +} diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogLevelConvertor.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogLevelConvertor.java new file mode 100644 index 0000000..b372d45 --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SysLogLevelConvertor.java @@ -0,0 +1,22 @@ +package com.bocloud.ams.booter.syslog; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.CompositeConverter; + +import java.util.HashMap; +import java.util.Map; + +public class SysLogLevelConvertor extends CompositeConverter { + + private static final Map MAP = new HashMap<>() {{ + this.put("DEBUG", "7"); + this.put("INFO", "6"); + this.put("WARN", "4"); + this.put("ERROR", "3"); + }}; + + @Override + protected String transform(ILoggingEvent iLoggingEvent, String s) { + return MAP.getOrDefault(iLoggingEvent.getLevel().toString(), iLoggingEvent.getLevel().toString()); + } +} \ No newline at end of file diff --git a/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SyslogOutputStreamTcpAndUdp.java b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SyslogOutputStreamTcpAndUdp.java new file mode 100644 index 0000000..c27be3c --- /dev/null +++ b/bocloud.ams.booter/src/main/java/com/bocloud/ams/booter/syslog/SyslogOutputStreamTcpAndUdp.java @@ -0,0 +1,70 @@ +package com.bocloud.ams.booter.syslog; + +import ch.qos.logback.core.net.SyslogOutputStream; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; + +public class SyslogOutputStreamTcpAndUdp extends SyslogOutputStream { + + private static final int MAX_LEN_TCP = 1024; + + private InetAddress addressTcp; + private Socket socketTcp; + private ByteArrayOutputStream baosTcp = new ByteArrayOutputStream(); + final private int portTcp; + + public SyslogOutputStreamTcpAndUdp(String syslogHost, int port) throws SocketException, UnknownHostException { + super(syslogHost, port); + this.addressTcp = InetAddress.getByName(syslogHost); + this.portTcp = port; + try { + this.socketTcp = new Socket(addressTcp, portTcp); + } catch (IOException e) { + throw new SocketException(e); + } + } + + @Override + public void write(byte[] byteArray, int offset, int len) throws IOException { + super.write(byteArray, offset, len); + baosTcp.write(byteArray, offset, len); + } + + @Override + public void flush() throws IOException { + super.flush(); + + byte[] bytes = baosTcp.toByteArray(); + + // clean up for next round + if (baosTcp.size() > MAX_LEN_TCP) { + baosTcp = new ByteArrayOutputStream(); + } else { + baosTcp.reset(); + } + + // after a failure, it can happen that bytes.length is zero + // in that case, there is no point in sending out an empty message/ + if (bytes.length == 0) { + return; + } + if (this.socketTcp != null) { + socketTcp.getOutputStream().write(bytes); + } + } + + @Override + public void close() { + super.close(); + addressTcp = null; + try { + socketTcp.close(); + } catch (IOException ignored) { + } + } +} diff --git a/bocloud.ams.booter/src/main/resources/application.yml b/bocloud.ams.booter/src/main/resources/application.yml new file mode 100644 index 0000000..5d5de06 --- /dev/null +++ b/bocloud.ams.booter/src/main/resources/application.yml @@ -0,0 +1,110 @@ +server: + port: '18081' + +spring: + application: + name: ams + thread: + core: + pool: + size: 1000 + max: + pool: + size: 1000 + queue: + capacity: 2000 + upload: + path: /home/cmp + cloud: + zookeeper: + connect-string: 10.20.12.65:2181 + home: /bocloud/cmp/product + auth: + username: bocloud + password: AES@CoU6oY/zuAoBbu6cdgOKlA== + config: + enabled: false + discovery: + register: true + enable: true + instance-host: 10.20.12.65 + instance-port: ${server.port} + root: ${spring.cloud.zookeeper.home}/services + conn: + timeout: '50000' + session: + timeout: '50000' + datasource: + druid: + dialect: mysql + url: jdbc:mysql://10.20.12.65:3306/ams?characterEncoding=utf8&useSSL=false + username: cmp + password: Gy2VghUgWHszx8gLFT4etT9ZVOukJi73KoG1q3Oz/DAz5h2mFVVunjcyaaKT9tMPsBgoWBFRmrYbhgqJqT/Q8A== + initialSize: '2' + maxActive: '30' + minIdle: '2' + maxWait: '60000' + poolPreparedStatements: 'true' + maxOpenPreparedStatements: '20' + maxPoolPreparedStatementPerConnectionSize: '20' + validationQuery: select 1 + validationQueryTimeout: '1' + testOnBorrow: 'true' + testOnReturn: 'true' + testWhileIdle: 'true' + remove-abandoned: 'true' + remove-abandoned-timeout: '60' + log-abandoned: 'true' + timeBetweenEvictionRunsMillis: '10000' + minEvictableIdleTimeMillis: '30001' + asyncCloseConnectionEnable: 'true' + filters: config,stat,wall,log4j + publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJfVJOpXYGy8aBCk3zEoKKQDTVCCvJwhhithfY/I5PUvzFBAYygunmuCtUhzPUZ+1RJQds0Q4fu07m5mr5kv5ocCAwEAAQ== + connectionProperties: config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJfVJOpXYGy8aBCk3zEoKKQDTVCCvJwhhithfY/I5PUvzFBAYygunmuCtUhzPUZ+1RJQds0Q4fu07m5mr5kv5ocCAwEAAQ==;druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + use-global-data-source-stat: 'true' + rabbitmq: + host: 10.20.12.65 + port: 5672 + username: admin + password: AES@CoU6oY/zuAoBbu6cdgOKlA== + virtual-host: cmp + dynamic: 'true' + banner: + charset: UTF-8 + freemarker: + checkTemplateLocation: 'false' + redis: + # standalone + host: 10.20.12.65 + port: 6379 + timeout: 60000ms + password: AES@CoU6oY/zuAoBbu6cdgOKlA== + lettuce: + pool: + max-active: '1024' + max-idle: '16' + min-idle: '4' + max-wait: -1ms + servlet: + multipart: + max-file-size: 2MB + max-request-size: 20MB + main: + allow-circular-references: true +logging: + config: classpath:logback-spring.xml + dir: /log/services + level: + root: info + com: + bocloud: info + file: + max-size: 100MB + max-history: '30' + total-size-cap: 2GB +collection: + task: + instance: + bakup: 0 0 4 * * ? + create-table: 0 1 0 1 * ? + diff --git a/bocloud.ams.booter/src/main/resources/banner.txt b/bocloud.ams.booter/src/main/resources/banner.txt new file mode 100644 index 0000000..fdcb37d --- /dev/null +++ b/bocloud.ams.booter/src/main/resources/banner.txt @@ -0,0 +1,8 @@ + ██████ ██ ██████ ████ ████ ███████ ██ ████ ████ ████████ +░█░░░░██ ██ ██ ░██ ██░░░░██░██░██ ██░██░██░░░░██ ████ ░██░██ ██░██ ██░░░░░░ +░█ ░██ █████ ░░██ ██ ██████ ███████ ░██ ██ ░░ ░██░░██ ██ ░██░██ ░██ ██░░██ ░██░░██ ██ ░██░██ +░██████ ██░░░██ ░░███ ██░░░░██░░██░░░██ ██████░██ ░██ ░░███ ░██░███████ ██ ░░██ ░██ ░░███ ░██░█████████ +░█░░░░ ██░███████ ░██ ░██ ░██ ░██ ░██ ██░░░██░██ ░██ ░░█ ░██░██░░░░ ██████████░██ ░░█ ░██░░░░░░░░██ +░█ ░██░██░░░░ ██ ░██ ░██ ░██ ░██░██ ░██░░██ ██░██ ░ ░██░██ ░██░░░░░░██░██ ░ ░██ ░██ +░███████ ░░██████ ██ ░░██████ ███ ░██░░██████ ░░██████ ░██ ░██░██ ░██ ░██░██ ░██ ████████ +░░░░░░░ ░░░░░░ ░░ ░░░░░░ ░░░ ░░ ░░░░░░ ░░░░░░ ░░ ░░ ░░ ░░ ░░ ░░ ░░ ░░░░░░░░ diff --git a/bocloud.ams.booter/src/main/resources/logback-spring.xml b/bocloud.ams.booter/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..4c50539 --- /dev/null +++ b/bocloud.ams.booter/src/main/resources/logback-spring.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + ${local_log_pattern} + + + + + + ${logging.dir}/${service.name}.log + + ${logging.dir}/history/${service.name}.%d{yyyy-MM-dd}.%i.log.gz + + + ${logging.file.max-size} + + ${logging.file.max-history} + ${logging.file.total-size-cap} + + + ${local_log_pattern} + + + + + + ${logging.syslog.host} + ${logging.syslog.port} + ${logging.syslog.facility} + ${sys_log_pattern} + + ${logging.syslog.level} + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bocloud.ams.entity/.gitignore b/bocloud.ams.entity/.gitignore new file mode 100644 index 0000000..e313482 --- /dev/null +++ b/bocloud.ams.entity/.gitignore @@ -0,0 +1,10 @@ +*/target/* +*/.settings/* +*.classpath +*.project +*.prefs +*.class +*.iml +/.idea/* +*/.svn/* +/target/ diff --git a/bocloud.ams.entity/pom.xml b/bocloud.ams.entity/pom.xml new file mode 100644 index 0000000..60db405 --- /dev/null +++ b/bocloud.ams.entity/pom.xml @@ -0,0 +1,18 @@ + + + + bocloud.ams + com.bocloud + 6.5.0-LTS-SZ + + 4.0.0 + bocloud.ams.entity + + + com.freedom + megatron.database + + + \ No newline at end of file diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/annotation/ColumnType.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/annotation/ColumnType.java new file mode 100644 index 0000000..0573d7c --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/annotation/ColumnType.java @@ -0,0 +1,14 @@ +package com.bocloud.ams.annotation; + +import java.lang.annotation.*; + +/** + * @author huliwei + * @date 2023/4/21 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@Inherited +public @interface ColumnType { + String value() default ""; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/Role.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/Role.java new file mode 100644 index 0000000..a0ff237 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/Role.java @@ -0,0 +1,16 @@ +package com.bocloud.ams.entity; + +import lombok.Data; + +/** + * @ClassName: Role + * @Description 角色 + * @Author yangzhenrong + * @Date 2022/5/24 14:00 + * @Version 1.0 + **/ +@Data +public class Role { + private Long id; + private String name; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/TableLog.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/TableLog.java new file mode 100644 index 0000000..0165ce6 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/TableLog.java @@ -0,0 +1,30 @@ +package com.bocloud.ams.entity; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author majiali + * @date 2023/4/20 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Table("ci_table_log") +public class TableLog extends GenericEntity { + // ID + @PK(value = PKStrategy.AUTO) + private Long id; + // 编码 + @Column("code") + private String code; + + @Column("template_table") + private String templateTable; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRule.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRule.java new file mode 100644 index 0000000..2825f19 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRule.java @@ -0,0 +1,46 @@ +package com.bocloud.ams.entity.association; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 16:27 + * @Description: + */ +@Data +@Table("ci_auto_relation_rule") +@EqualsAndHashCode(callSuper = true) +public class AutoRelationRule extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column(value = "module_relation_id") + private Long moduleRelationId; + @Column(value = "relation_category_id") + private Long relationCategoryId; + @Column(value = "source_module_id") + private Long sourceModuleId; + @Column(value = "target_module_id") + private Long targetModuleId; + @IgnoreAll + private List items; + @IgnoreAll + private String sourceModuleName; + @IgnoreAll + private String targetModuleName; + @IgnoreAll + private String cmdbRelationCategoryName; + @IgnoreAll + private String cmdbRelationName; + @IgnoreAll + private String creator; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItem.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItem.java new file mode 100644 index 0000000..b994383 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItem.java @@ -0,0 +1,71 @@ +package com.bocloud.ams.entity.association; + + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateDeserializer; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.*; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 16:31 + * @Description: + */ +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +@Table("ci_auto_relation_rule_item") +@EqualsAndHashCode(callSuper = true) +public class AutoRelationRuleItem extends Generic { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column(value = "relation_rule_id") + private Long relationRuleId; + @Column(value = "source_field") + private Long sourceField; + @Column(value = "target_field") + private Long targetField; + @Column(value = "is_deleted") + private Boolean deleted; + @Column(value = "remark") + private String remark; + @IgnoreUpdate + @Column(value = "gmt_create", nullable = false) + @JsonSerialize(using = DateSerializer.class) + @JsonDeserialize(using = DateDeserializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + @Column("gmt_modify") + @JsonSerialize(using = DateSerializer.class) + @JsonDeserialize(using = DateDeserializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtModify; + @IgnoreUpdate + @Column("creator_id") + private Long creatorId; + @Column("mender_id") + private Long menderId; + @IgnoreAll + private List values; + @IgnoreAll + private String sourceFieldName; + @IgnoreAll + private String targetFieldName; + @IgnoreAll + private String sourceFieldType; + @IgnoreAll + private String targetFieldType; + @IgnoreAll + private String sourceFieldCode; + @IgnoreAll + private String targetFieldCode; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItemValue.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItemValue.java new file mode 100644 index 0000000..742b952 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/association/AutoRelationRuleItemValue.java @@ -0,0 +1,79 @@ +package com.bocloud.ams.entity.association; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateDeserializer; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.*; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @Author liuyuanyuan + * @Date 2022/5/11 0011 18:59 + * @Description: + */ +@Data +@Table("ci_auto_relation_rule_item_value") +@EqualsAndHashCode(callSuper = true) +public class AutoRelationRuleItemValue extends Generic { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column(value = "relation_rule_id") + private Long relationRuleId; + @Column(value = "item_id") + private Long itemId; + @Column(value = "source_module_id") + private Long isSourceId; + @Column(value = "target_module_id") + private Long isTargetId; + @Column(value = "source_property_id") + private Long sourceValue; + @Column(value = "target_property_id") + private Long targetValue; + @Column(value = "is_deleted") + private Boolean deleted; + @Column(value = "remark") + private String remark; + @IgnoreUpdate + @Column(value = "gmt_create", nullable = false) + @JsonSerialize(using = DateSerializer.class) + @JsonDeserialize(using = DateDeserializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + @Column("gmt_modify") + @JsonSerialize(using = DateSerializer.class) + @JsonDeserialize(using = DateDeserializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtModify; + @IgnoreUpdate + @Column("creator_id") + private Long creatorId; + @Column("mender_id") + private Long menderId; + + /** + * 规则结构项code + */ + @IgnoreAll + private String sourceFieldCode; + @IgnoreAll + private String targetFieldCode; + + @IgnoreAll + private String sourceFieldName; + @IgnoreAll + private String targetFieldName; + + @IgnoreAll + private String sourceFieldType; + @IgnoreAll + private String targetFieldType; + + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAudit.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAudit.java new file mode 100644 index 0000000..6671efc --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAudit.java @@ -0,0 +1,58 @@ +package com.bocloud.ams.entity.audit; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author liuyuanyuan + * @Date 2022/5/23 0023 17:47 + * @Description: + */ +@Data +@Table("ci_operational_audit") +@EqualsAndHashCode(callSuper = true) +public class OperationalAudit extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + + @Column("type_code") + private String typeCode; + + /** + * 操作类型 + */ + @Column("type") + private String type; + + /** + * 变更前 + */ + @Column("oa_before") + private String oaBefore; + + /** + * 变更后 + */ + @Column("oa_after") + private String oaAfter; + + @Column("module_code") + private String moduleCode; + + @Column("instance_id") + private Long instanceId; + + @Column("operator") + private String operator; + + @IgnoreAll + private String dateStr; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAuditBak.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAuditBak.java new file mode 100644 index 0000000..2d6e9be --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/audit/OperationalAuditBak.java @@ -0,0 +1,110 @@ +package com.bocloud.ams.entity.audit; + + +import com.bocloud.ams.annotation.ColumnType; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateDeserializer; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreUpdate; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @Author majiali + * @Date 2023/4/240023 17:47 + * @Description: + */ + +@Data +@Table("ci_operational_audit_bak") +public class OperationalAuditBak extends Generic { + @PK(value = PKStrategy.SELF) + private Long id; + + @Column(value = "type_code",length=100) + private String typeCode; + + /** + * 操作类型 + */ + @Column(value = "type",length=100) + private String type; + + /** + * 变更前 + */ + @ColumnType(value = "text") + @Column(value = "oa_before") + private String oaBefore; + + /** + * 变更后 + */ + @ColumnType(value = "text") + @Column(value = "oa_after") + private String oaAfter; + + @Column(value = "module_code",length=100) + private String moduleCode; + + @Column(value = "instance_id") + private Long instanceId; + + @Column(value = "operator",length=500) + private String operator; + + @IgnoreUpdate + @Column( + value = "gmt_create", + nullable = false + ) + @JsonSerialize( + using = DateSerializer.class + ) + @JsonDeserialize( + using = DateDeserializer.class + ) + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + private Date gmtCreate; + @Column("gmt_modify") + @JsonSerialize( + using = DateSerializer.class + ) + @JsonDeserialize( + using = DateDeserializer.class + ) + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + private Date gmtModify; + @IgnoreUpdate + @Column("creator_id") + private Long creatorId; + @Column("owner_id") + private Long ownerId; + @Column("mender_id") + private Long menderId; + @Column(value = "name",length = 100) + private String name; + @Column(value = "status",length = 16) + private String status; + @Column("is_deleted") + private Boolean deleted; + @Column(value = "props",length = 1000) + private String props; + @Column(value = "remark",length = 1000) + private String remark; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionComponent.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionComponent.java new file mode 100644 index 0000000..33baaf6 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionComponent.java @@ -0,0 +1,48 @@ +package com.bocloud.ams.entity.collection; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 13:39 + * @Description: + */ +@Data +@Table("ci_collection_component") +@EqualsAndHashCode(callSuper = true) +public class CollectionComponent extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("template_id") + private Long templateId; + @Column("type") + private String type; + @Column("title") + private String title; + @Column("input_form") + private String inputForm; + @Column("parameter_type") + private String parameterType; + @Column("module_id") + private Long moduleId; + @Column("module_code") + private String moduleCode; + @Column("property_id") + private Long propertyId; + @Column("property_code") + private String propertyCode; + @IgnoreAll + private String creator; + @IgnoreAll + private String moduleName; + @IgnoreAll + private String propertyName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistory.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistory.java new file mode 100644 index 0000000..6ccf72c --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistory.java @@ -0,0 +1,58 @@ +package com.bocloud.ams.entity.collection; + + +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.entity.bean.Generic; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @ClassName: CollectionHistory + * @Description 采集记录 + * @Author yangzhenrong + * @Date 2022/6/15 19:57 + * @Version 1.0 + **/ +@Data +@Table("ci_collection_history") +@EqualsAndHashCode(callSuper = true) +public class CollectionHistory extends Generic { + @PK + private Long id; + @Column(value = "module_id") + private Long moduleId; + @Column(value = "instance_id") + private Long instanceId; + @Column(value = "instance_uuid") + private String instanceUuid; + @Column(value = "task_instance_id", nullable = false) + private Long taskInstanceId; + @Column(value = "type", length = 64, nullable = false) + private String type;//取值范围:ADD、EDIT + @Column(value = "status", length = 64, nullable = false) + private String status;//取值范围:SUCCESS、FAILED、RECONCILED未调和 + @Column(value = "output") + private String output;//原始输出 + @Column(value = "operator", length = 128, nullable = false) + private String operator; + @Column(value = "gmt_create", length = 64, nullable = false) + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + @Column(value = "reason") + private String reason;//原因 + @IgnoreAll + private List historyItems; + @IgnoreAll + private String tableName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryBak.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryBak.java new file mode 100644 index 0000000..80d0cf2 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryBak.java @@ -0,0 +1,53 @@ +package com.bocloud.ams.entity.collection; + +import com.bocloud.ams.annotation.ColumnType; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @author huliwei + * @date 2023/4/25 + */ +@Data +@Table("ci_collection_history_bak") +public class CollectionHistoryBak extends Generic { + + @PK(value = PKStrategy.SELF) + private Long id; + @Column(value = "module_id") + private Long moduleId; + @Column(value = "instance_id") + private Long instanceId; + @Column(value = "instance_uuid",length = 256) + private String instanceUuid; + @Column(value = "task_instance_id", nullable = false) + private Long taskInstanceId; + @Column(value = "type", length = 64, nullable = false) + private String type;//取值范围:ADD、EDIT + @Column(value = "status", length = 64) + private String status;//取值范围:SUCCESS、FAILED、RECONCILED未调和 + @ColumnType(value = "longtext") + @Column(value = "output") + private String output;//原始输出 + @Column(value = "operator", length = 128, nullable = false) + private String operator; + @Column(value = "gmt_create", length = 64, nullable = false) + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + @Column(value = "reason",length = 2048) + private String reason;//原因 + @IgnoreAll + private List historyItems; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItem.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItem.java new file mode 100644 index 0000000..bea02da --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItem.java @@ -0,0 +1,41 @@ +package com.bocloud.ams.entity.collection; + + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.Generic; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @ClassName: CollectionHistory + * @Description 采集记录详情 + * @Author yangzhenrong + * @Date 2022/6/15 19:57 + * @Version 1.0 + **/ +@Data +@Table("ci_collection_history_item") +@EqualsAndHashCode(callSuper = true) +public class CollectionHistoryItem extends Generic { + @PK + private Long id; + @Column(value = "history_id", nullable = false) + private Long historyId; + @Column(value = "property_id", nullable = false) + private Long propertyId; + @Column(value = "property_code", length = 256, nullable = false) + private String propertyCode; + @Column(value = "before_value", length = 2056) + private String beforeValue; + @Column(value = "after_value", length = 2056) + private String afterValue; + @IgnoreAll + private String propertyName; + @IgnoreAll + private String tableName; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItemBak.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItemBak.java new file mode 100644 index 0000000..842ac35 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionHistoryItemBak.java @@ -0,0 +1,34 @@ +package com.bocloud.ams.entity.collection; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; + +/** + * @author huliwei + * @date 2023/4/25 + */ +@Data +@Table("ci_collection_history_item_bak") +public class CollectionHistoryItemBak extends Generic { + + @PK(value = PKStrategy.SELF) + private Long id; + @Column(value = "history_id", nullable = false) + private Long historyId; + @Column(value = "property_id", nullable = false) + private Long propertyId; + @Column(value = "property_code", length = 256, nullable = false) + private String propertyCode; + @Column(value = "before_value", length = 2056) + private String beforeValue; + @Column(value = "after_value", length = 2056) + private String afterValue; + @IgnoreAll + private String propertyName; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTask.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTask.java new file mode 100644 index 0000000..87abda6 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTask.java @@ -0,0 +1,47 @@ +package com.bocloud.ams.entity.collection; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 17:03 + * @Description: + */ +@Data +@Table("ci_collection_task") +@EqualsAndHashCode(callSuper = true) +public class CollectionTask extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("uuid") + private String uuid; + @Column("type") + private String type; + @Column("graph") + private Object graph; + @Column("cron") + private String cron; + @Column("module_id") + private Long moduleId; + @Column("template_id") + private Long templateId; + @Column("reconcile") + private Boolean reconcile = false; + @Column("auto_relation") + private Boolean autoRelation = false; + @IgnoreAll + private String creator; + @IgnoreAll + private String mender; + @IgnoreAll + private String templateName; + @IgnoreAll + private String moduleName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstance.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstance.java new file mode 100644 index 0000000..9fe686e --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstance.java @@ -0,0 +1,142 @@ +package com.bocloud.ams.entity.collection; + + +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/6/10 0010 16:11 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("ci_collection_task_instance") +@EqualsAndHashCode(callSuper = true) +public class CollectionTaskInstance extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("uuid") + private String uuid; + /** + * 任务类型 + */ + @Column("type") + private String type; + @Column("code") + private String code; + @Column("graph") + private Object graph; + @Column("cron") + private String cron; + /** + * 开始时间 + */ + @Column("gmt_start") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS") + private Date gmtStart; + /** + * 结束时间 + */ + @Column("gmt_finish") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS") + private Date gmtFinish; + + /** + * 总耗时 + */ + @Column("finish_time") + private Long finishTime; + + /** + * 任务ID + */ + @Column("task_id") + private Long taskId; + /** + * 超时时间 + */ + @Column("timeout") + private Long timeout; + + /** + * 耗时 + */ + @Column("cost") + private Double cost; + + /** + * 输入参数 + */ + @Column("input") + private String input; + + /** + * 输出参数 + */ + @Column("output") + private String output; + + /** + * 采集结束时间 + */ + @Column("collection_finish") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date collectionFinish; + + /** + * 采集总耗时 + */ + @Column("collection_time") + private Double collectionTime; + + /** + * 采集状态 + */ + @Column("collection_status") + private String collectionStatus; + + @IgnoreAll + private List successes; + @IgnoreAll + private List failures; + @IgnoreAll + private Long moduleId; + @IgnoreAll + private String moduleCode; + @IgnoreAll + private String creator; + @IgnoreAll + private String tableName; + + public CollectionTaskInstance(Long creatorId, Long ownerId, Long menderId, String name, String status, String remark, + String type, String cron, String collectionStatus) { + this.setName(name); + this.setStatus(status); + this.setRemark(remark); + this.type = type; + this.cron = cron; + this.setCreatorId(creatorId); + this.setOwnerId(ownerId); + this.setMenderId(menderId); + this.collectionStatus = collectionStatus; + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstanceBak.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstanceBak.java new file mode 100644 index 0000000..8464992 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTaskInstanceBak.java @@ -0,0 +1,160 @@ +package com.bocloud.ams.entity.collection; + +import com.bocloud.ams.annotation.ColumnType; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateDeserializer; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.*; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; + +/** + * @author huliwei + * @date 2023/4/24 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table("ci_collection_task_instance_bak") +public class CollectionTaskInstanceBak extends Generic { + @PK(value = PKStrategy.SELF) + private Long id; + @Column(value = "uuid",length = 64) + private String uuid; + /** + * 任务类型 + */ + @Column(value = "type",length = 64) + private String type; + @Column(value = "code",length = 64) + private String code; + @ColumnType(value = "longtext") + @Column("graph") + private String graph; + @Column(value = "cron",length = 64) + private String cron; + /** + * 开始时间 + */ + @Column("gmt_start") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS") + private Date gmtStart; + /** + * 结束时间 + */ + @Column("gmt_finish") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS") + private Date gmtFinish; + + /** + * 总耗时 + */ + @Column("finish_time") + private Long finishTime; + + /** + * 任务ID + */ + @Column("task_id") + private Long taskId; + /** + * 超时时间 + */ + @Column("timeout") + private Long timeout; + + /** + * 耗时 + */ + @ColumnType(value = "double") + @Column("cost") + private Double cost; + + /** + * 输入参数 + */ + @ColumnType(value = "text") + @Column("input") + private String input; + + /** + * 输出参数 + */ + @ColumnType(value = "longtext") + @Column("output") + private String output; + + /** + * 采集结束时间 + */ + @Column("collection_finish") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date collectionFinish; + + /** + * 采集总耗时 + */ + @ColumnType(value = "double") + @Column("collection_time") + private Double collectionTime; + + /** + * 采集状态 + */ + @Column(value = "collection_status",length = 64) + private String collectionStatus; + + @IgnoreUpdate + @Column( + value = "gmt_create", + nullable = false + ) + @JsonSerialize( + using = DateSerializer.class + ) + @JsonDeserialize( + using = DateDeserializer.class + ) + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + private Date gmtCreate; + @Column("gmt_modify") + @JsonSerialize( + using = DateSerializer.class + ) + @JsonDeserialize( + using = DateDeserializer.class + ) + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + private Date gmtModify; + @IgnoreUpdate + @Column(value = "creator_id",nullable = false) + private Long creatorId; + @Column("owner_id") + private Long ownerId; + @Column("mender_id") + private Long menderId; + @Column(value = "name" , length = 256) + private String name; + @Column(value = "status" ,length = 16) + private String status; + @Column(value = "is_deleted",length = 1,nullable = false) + private Boolean deleted; + @Column(value = "props",length = 1024) + private String props; + @Column(value = "remark",length = 512) + private String remark; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTemplate.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTemplate.java new file mode 100644 index 0000000..1f36020 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/collection/CollectionTemplate.java @@ -0,0 +1,37 @@ +package com.bocloud.ams.entity.collection; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 11:10 + * @Description: + */ +@Data +@Table("ci_collection_template") +@EqualsAndHashCode(callSuper = true) +public class CollectionTemplate extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("module_id") + private Long moduleId; + @Column("graph") + private Object graph; + @Column("collection_type") + private String collectionType; + @IgnoreAll + private List components; + @IgnoreAll + private String creator; + @IgnoreAll + private String moduleName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/config/CmdbConfig.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/config/CmdbConfig.java new file mode 100644 index 0000000..dddd3db --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/config/CmdbConfig.java @@ -0,0 +1,101 @@ +package com.bocloud.ams.entity.config; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreUpdate; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.Generic; +import com.megatron.entity.meta.PKStrategy; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @author majiali + * @date 2023/4/20 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Table("ci_cmdb_config") +public class CmdbConfig extends Generic { + + /** + * id + */ + @PK(value = PKStrategy.AUTO) + private Long id; + /** + * 配置编码 + */ + @Column("code") + private String code; + /** + * 配置名称 + */ + @Column("name") + private String name; + /** + * 配置值 + */ + @Column("value") + private String value; + /** + * 配置注释 + */ + @Column("remark") + private String remark; + /** + * 配置分类 + */ + @Column("category") + private String category; + + /** + * 配置子类 + */ + @Column("subclass") + private String subclass; + /** + * 配置类型(TEXT、SELECTICON、PASSWORD) + */ + @Column("type") + private String type; + /** + * 配置json串 + */ + @Column("config") + private String config; + /** + * 创建人id + */ + @Column("creator_id") + private Long creatorId; + /** + * 修改人Id + */ + @Column("mender_id") + private Long menderId; + /** + * 创建时间 + */ + @Column("gmt_create") + @IgnoreUpdate + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + /** + * 修改时间 + */ + @Column("gmt_modify") + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtModify; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/ApplyStatus.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/ApplyStatus.java new file mode 100644 index 0000000..b7ac24b --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/ApplyStatus.java @@ -0,0 +1,36 @@ +package com.bocloud.ams.entity.enums; + +/** + * 申请状态 + * + * @author dmw + * + */ +public enum ApplyStatus { + + /** + * 新创建 + */ + CREATED, + /** + * 未申请 + */ + UNAPPLY, + /** + * 审批中 + */ + APPROVING, + /** + * 已通过 + */ + APPROVED, + /** + * 已拒绝 + */ + REFUSED, + /** + * 编排中 + */ + DEVELOPING, + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/CollectionEnum.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/CollectionEnum.java new file mode 100644 index 0000000..1163472 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/CollectionEnum.java @@ -0,0 +1,220 @@ +package com.bocloud.ams.entity.enums; + + +import com.megatron.common.model.GeneralResult; +import org.apache.commons.lang3.StringUtils; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 13:42 + * @Description: + */ +public class CollectionEnum { + + public enum Task { + /** + * 定时任务 + */ + SCHEDULED("scheduled"), + /** + * 标准任务 + */ + STANDARD("standard"), + /** + * 临时任务 + */ + TEMPORARY("temporary"), + /** + * 任务模板 + */ + TEMPLATE("template"); + + public static GeneralResult hasValue(String value) { + if (StringUtils.isEmpty(value)) { + return new GeneralResult<>(false, "参数为空!"); + } + Task[] tasks = Task.values(); + for (Task task : tasks) { + if (task.name().equalsIgnoreCase(value)) { + return new GeneralResult(true, task, "success"); + } + } + return new GeneralResult<>(false, "数值不存在!"); + } + + private String value; + + Task(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } + } + + /** + * 任务执行状态 + */ + public enum Status { + /** + * 创建 + */ + CREATED, + /** + * 运行中 + */ + RUNNING, + /** + * 已暂停 + */ + SUSPENDED, + /** + * 成功 + */ + SUCCESS, + /** + * 失败 + */ + ERROR + } + + public enum workerCode { + //脚本 + SCRIPT("task.maintain.script"), + //数据库 + DATABASE("task.maintain.database"), + //接口 + METHOD("task.maintain.method"); + + private final String value; + + workerCode(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum collectionType { + //脚本 + SCRIPT("script"), + //数据库 + DATABASE("database"), + //接口 + METHOD("method"); + + private final String value; + + collectionType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum parameter { + //输入参数 + INPUT("input"), + //目标输入参数 + INPUT_TARGET("input_target"), + //输出参数 + OUTPUT("output"), + //对照参数 + CONTRAST("contrast"); + + private final String value; + + parameter(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum inputForm { + //输入形式 + MANUAL("manual"); + private final String value; + + inputForm(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum parameterType { + //cmdb实例 + CMDB_INSTANCE("cmdb_instance"), + //单行文本 + TEXT("text"), + //加密数据 + ENCRYPT_DATA("encrypt_data"), + //整数 + INTEGER("integer"); + + private final String value; + + parameterType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum historyType { + ADD("实例新增"), + EDIT("实例变更"), + NOUPDATE("无需更新"), + NOTCOLLECTED("未采集"); + private final String value; + + historyType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum historyStatus { + SUCCESS("执行成功"), + FAILED("执行失败"), + RECONCILED("未调和"); + private final String value; + + historyStatus(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum historyOperate { + CANCEL("取消"), + UPDATE("更新"); + private final String value; + + historyOperate(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/InstanceEnum.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/InstanceEnum.java new file mode 100644 index 0000000..6bcc7c4 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/InstanceEnum.java @@ -0,0 +1,66 @@ +package com.bocloud.ams.entity.enums; + + +public class InstanceEnum { + + public enum type { + ALL_UPDATE,//全部更新 + CLEAN_DATA//清空数据 + } + + public enum catalog { + INSTANCE("实例"), + RELATION("关联关系"); + + private String value; + + catalog(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum category { + CREATE("新增"), + MODIFY("编辑"), + DEL("删除"), + BATCH_MODIFY("批量编辑"), + BATCH_DELETE("批量删除"); + + private String value; + + category(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum authority { + ACCESS("ACCESS", "实例访问"), + EDIT("EDIT", "实例编辑"), + DEL("DEL", "实例删除"), + AUTH_MANAGE("AUTH_MANAGE", "实例权限管理"); + + private String value; + private String name; + + authority(String value, String name) { + this.value = value; + this.name = name; + } + + public String getValue() { + return value; + } + + public String getName() { + return name; + } + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/OperationalAuditType.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/OperationalAuditType.java new file mode 100644 index 0000000..72c7540 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/OperationalAuditType.java @@ -0,0 +1,49 @@ +package com.bocloud.ams.entity.enums; + +/** + * 审计日志操作类型 + */ +public enum OperationalAuditType { + //新增 + ADD("ADD", "新增"), + //修改 + MODIFY("MODIFY", "修改"), + //批量修改 + BATCH_MODIFY("BATCH_MODIFY", "批量修改"), + //删除 + DELETE("DEL", "删除"), + //批量删除 + BATCH_DELETE("BATCH_DELETE", "批量删除"), + //分配 + ALLOCATION("ALLOCATION", "分配"), + //转移 + TRANSFER("TRANSFER", "转移"), + //关联 + RELATION("RELATION", "关联"), + //取消关联 + ASSOCIATION("ASSOCIATION", "取消关联"); + + private String type; + private String typeDesc; + + OperationalAuditType(String type, String typeDesc) { + this.type = type; + this.typeDesc = typeDesc; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getTypeDesc() { + return typeDesc; + } + + public void setTypeDesc(String typeDesc) { + this.typeDesc = typeDesc; + } +} \ No newline at end of file diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/PropertyType.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/PropertyType.java new file mode 100644 index 0000000..6ad3b7c --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/PropertyType.java @@ -0,0 +1,57 @@ +package com.bocloud.ams.entity.enums; + +/** + * 属性类型 + * + * @author tangcq + */ +public enum PropertyType { + /** + * 单行文本 + */ + TEXTFIELD, + /** + * 文本框 + */ + TEXTAREA, + /** + * 下来菜单 + */ + SELECT, + /** + * 单选 + */ + RADIO, + /** + * 多选 + */ + CHECKBOX, + /** + * 引用 + */ + QUOTE, + /** + * 日期 + */ + DATE, + /** + * 日期+时间 + */ + TIME, + /** + * 加密 + */ + TEXTENCRYPT, + /** + * 整数 + */ + INTEGER, + /** + * 小数 + */ + FLOAT, + /** + * 表格 + */ + TABLE, +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/Status.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/Status.java new file mode 100644 index 0000000..a6eec9e --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/enums/Status.java @@ -0,0 +1,126 @@ +package com.bocloud.ams.entity.enums; + +/** + * 状态枚举类 + * + * @author dmw + * + */ +public class Status { + + /** + * 任务状态 + * + * @author dmw + * + */ + public static enum Task { + + } + + /** + * 任务实例状态 + * + * @author dmw + * + */ + /** + * @author weiwei + * + */ + /** + * @author weiwei + * + */ + public static enum Inst { + /** + * 新创建 + */ + CREATED, + /** + * 等待中 + */ + WAITTING, + /** + * 运行中 + */ + RUNNING, + /** + * 已暂停 + */ + SUSPENDED, + /** + * 成功 + */ + SUCCESS, + /** + * 失败 + */ + FAILED, + /** + * 异常 + */ + EXCEPTION, + /** + * 取消中 + */ + CANCELING, + /** + * 已取消 + */ + CANCELED, + /** + * 申请中 + */ + APPROVING, + /** + * 已结束 + */ + END; + } + + /** + * 任务节点状态 + * + * @author dmw + * + */ + public static enum Node { + /** + * 不可执行 + */ + NOREADY, + /** + * 可执行 + */ + READY, + /** + * 运行中 + */ + RUNNING, + /** + * 成功 + */ + SUCCESS, + /** + * 失败 + */ + FAILED, + /** + * 异常 + */ + EXCEPTION, + /** + * 已暂停 + */ + SUSPENDED, + /** + * 已跳过 + */ + SKIPPED, + /** + * 已取消 + */ + CANCELED; + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/Instance.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/Instance.java new file mode 100644 index 0000000..95737f1 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/Instance.java @@ -0,0 +1,35 @@ +package com.bocloud.ams.entity.instance; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @ClassName: CmdbInstance + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 14:45 + * @Version 1.0 + **/ +@Data +@Table("ci_instance") +@EqualsAndHashCode(callSuper = true) +public class Instance extends GenericEntity { + + @PK + private Long id; + @Column(value = "uuid", length = 256, nullable = false) + private String uuid; + @Column(value = "module_id", nullable = false) + private Long moduleId; + @Column(value = "module_code", length = 128, nullable = false) + private String moduleCode; + @IgnoreAll + private List instanceValues; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceAuthority.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceAuthority.java new file mode 100644 index 0000000..bfdf0b1 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceAuthority.java @@ -0,0 +1,64 @@ +package com.bocloud.ams.entity.instance; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @ClassName: CmdbInstanceAuthority + * @Description + * @Author yangzhenrong + * @Date 2022/5/23 18:10 + * @Version 1.0 + **/ +@Data +@Table("ci_instance_authority") +@EqualsAndHashCode(callSuper = true) +public class InstanceAuthority extends GenericEntity { + @PK + private Long id; + @Column(value = "module_id", nullable = false) + private Long moduleId; + @Column(value = "instance_id", nullable = false) + private Long instanceId; + @Column(value = "role_id", nullable = false) + private Long roleId; + @Column(value = "user_id") + private Long userId; + @Column(value = "auths", length = 512, nullable = false) + private String auths; + @IgnoreAll + private Boolean isOverwrite; + @IgnoreAll + private List instanceIds; + @IgnoreAll + private String roleName; + @IgnoreAll + private String authNames; + @IgnoreAll + private String userName; + @IgnoreAll + private String userIds; + + public InstanceAuthority() { + + } + + public InstanceAuthority(Long moduleId, Long instanceId, Long roleId, Long userId, String auths) { + this.moduleId = moduleId; + this.instanceId = instanceId; + this.roleId = roleId; + this.userId = userId; + this.auths = auths; + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceHistory.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceHistory.java new file mode 100644 index 0000000..e15e691 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceHistory.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.entity.instance; + + +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.entity.bean.Generic; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @ClassName: CmdbInstanceHistory + * @Description 实例操作记录 + * @Author yangzhenrong + * @Date 2022/5/16 15:49 + * @Version 1.0 + **/ +@Data +@Table("ci_instance_history") +@EqualsAndHashCode(callSuper = true) +public class InstanceHistory extends Generic { + @PK + private Long id; + @Column(value = "module_id", nullable = false) + private Long moduleId; + @Column(value = "instance_id", nullable = false) + private Long instanceId; + @Column(value = "catalog", length = 64, nullable = false) + private String catalog;//取值范围:INSTANCE、RELATION + @Column(value = "category", length = 64, nullable = false) + private String category;//取值范围:CREATE、MODIFY、REMOVE + @Column(value = "content", length = 1024, nullable = false) + private String content; + @Column(value = "operator", length = 128, nullable = false) + private String operator; + @Column(value = "gmt_create", length = 64, nullable = false) + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtCreate; + + public InstanceHistory() { + + } + + public InstanceHistory(Long moduleId, Long instanceId, String catalog, String category, String content, String operator, Date gmtCreate) { + this.moduleId = moduleId; + this.instanceId = instanceId; + this.catalog = catalog; + this.category = category; + this.content = content; + this.operator = operator; + this.gmtCreate = gmtCreate; + } + + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelation.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelation.java new file mode 100644 index 0000000..e1c610e --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelation.java @@ -0,0 +1,80 @@ +package com.bocloud.ams.entity.instance; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/5/16 0016 14:09 + * @Description: + */ +@Data +@Table("ci_instance_relation") +@EqualsAndHashCode(callSuper = true) +public class InstanceRelation extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column(value = "relation_category_id", nullable = false) + private Long relationCategoryId; + @Column(value = "relation_category_code", nullable = false, length = 256) + private String relationCategoryCode; + @Column(value = "module_relation_id", nullable = false) + private Long moduleRelationId; + @Column(value = "module_relation_name", length = 256) + private String moduleRelationName; + @Column(value = "source_module_id", nullable = false) + private Long sourceModuleId; + @Column(value = "source_module_code", nullable = false, length = 256) + private String sourceModuleCode; + @Column(value = "source_instance_id", nullable = false) + private Long sourceInstanceId; + @Column(value = "source_instance_name", length = 256) + private String sourceInstanceName; + @Column(value = "target_module_id", nullable = false) + private Long targetModuleId; + @Column(value = "target_module_code", nullable = false, length = 256) + private String targetModuleCode; + @Column(value = "target_instance_id", nullable = false) + private Long targetInstanceId; + @Column(value = "target_instance_name", length = 256) + private String targetInstanceName; + /** + * 关联方式: 手动-MANUAL 自动-AUTO + */ + @Column(value = "way", length = 32) + private String way; + @IgnoreAll + private String sourceType; + @IgnoreAll + private String targetType; + @IgnoreAll + private Long relationId; + @IgnoreAll + private String relationName; + @IgnoreAll + private List cmdbInstanceRelations; + + /** + * 实例之间的关系 与 模型定义之间的关系 是否一致 + * false 是一致 ; true 是相反 + */ + @IgnoreAll + private Boolean isReversed = false; + @IgnoreAll + private String type; + @IgnoreAll + private Long currentModuleId; + /** + * 手动关系,标记当前操作的实例 + */ + @IgnoreAll + private Long currentInstanceId; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelationHistoryRecord.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelationHistoryRecord.java new file mode 100644 index 0000000..c7b259d --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceRelationHistoryRecord.java @@ -0,0 +1,92 @@ +package com.bocloud.ams.entity.instance; + + + +import com.megatron.common.utils.DateDeserializer; +import com.megatron.common.utils.DateSerializer; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @ClassName: CmdbInstanceRelationHistoryRecord + * @Description 历史关系变更历史记录 + * @Author majiali + * @Date 2022/6/8 15:49 + * @Version 1.0 + **/ +@Data +@Table("ci_instance_relation_history_record") +@EqualsAndHashCode(callSuper = true) +public class InstanceRelationHistoryRecord extends GenericEntity { + @PK + private Long id; + @Column("module_id") + private Long moduleId; + @Column("instance_id") + private Long instanceId; + /** + * 操作类型: 取消关联 cancel 关联 relation + */ + @Column("type") + private String type; + /** + * 关联方式: 手动-MANUAL 自动-AUTO + */ + @Column("way") + private String way; + /** + * 当前资源是否是源模型实例 1:是 0:否 + */ + @Column("is_source") + private Boolean isSource; + @Column("module_relation_id") + private Long moduleRelationId; + @Column("relation_category_id") + private Long relationCategoryId; + @Column("auto_relation_rule_id") + private Long autoRelationRuleId; + @Column("alter_before") + private String alterBefore; + @Column("alter_after") + private String alterAfter; + @Column("reason") + private String reason; + @Column("relation_instance_id") + private Long relationInstanceId; + + @Column("exec_time") + @JsonSerialize( + using = DateSerializer.class + ) + @JsonDeserialize( + using = DateDeserializer.class + ) + @DateTimeFormat( + pattern = "yyyy-MM-dd HH:mm:ss" + ) + private Date execTime; + @Column("exec_id") + private Long execId; + @IgnoreAll + private String executor; + @IgnoreAll + private String creator; + @IgnoreAll + private String moduleRelationName; + @IgnoreAll + private String relationCategoryName; + @IgnoreAll + private String moduleCode; + @IgnoreAll + private String moduleName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceValue.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceValue.java new file mode 100644 index 0000000..2c927ec --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/instance/InstanceValue.java @@ -0,0 +1,40 @@ +package com.bocloud.ams.entity.instance; + +import com.bocloud.ams.entity.module.Property; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @ClassName: CmdbInstanceValue + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 14:51 + * @Version 1.0 + **/ +@Data +@Table("ci_instance_value") +@EqualsAndHashCode(callSuper = true) +public class InstanceValue extends GenericEntity { + @PK + private Long id; + @Column(value = "instance_id", nullable = false) + private Long instanceId; + @Column(value = "property_id", nullable = false) + private Long propertyId; + @Column(value = "property_value", length = 2056) + private String propertyValue; + @Column(value = "property_code", length = 256, nullable = false) + private String propertyCode; + @IgnoreAll + private String uuid; + @IgnoreAll + private Long moduleId; + @IgnoreAll + private Property property; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/CollectionHistoryModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/CollectionHistoryModel.java new file mode 100644 index 0000000..0c2ba96 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/CollectionHistoryModel.java @@ -0,0 +1,11 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class CollectionHistoryModel { + private List ids; + private String action; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnAndSearchItemModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnAndSearchItemModel.java new file mode 100644 index 0000000..f5fb6d7 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnAndSearchItemModel.java @@ -0,0 +1,24 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: 实例拓扑中资源列表的搜索项以及列表的列名 + * @date 2022/5/18 18:08 + */ +@Data +public class ColumnAndSearchItemModel { + /** + * 搜索项 + */ + private List searchConfigs; + /** + * 列表字段 + */ + private List columns; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnModel.java new file mode 100644 index 0000000..a89aeb1 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ColumnModel.java @@ -0,0 +1,32 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: { label: '应用系统名称', value: 'name' } + * @date 2022/5/19 11:07 + */ +@Data +public class ColumnModel { + /** + * 列表名称name + */ + private String label; + /** + * 列表key + */ + private String prop; + + public ColumnModel(String label, String prop) { + super(); + this.label = label; + this.prop = prop; + } + + public ColumnModel() { + super(); + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceBean.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceBean.java new file mode 100644 index 0000000..07e90b6 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceBean.java @@ -0,0 +1,22 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +import java.util.List; + +/** + * @ClassName: CmdbInstanceModel + * @Description + * @Author yangzhenrong + * @Date 2022/5/24 17:08 + * @Version 1.0 + **/ +@Data +public class InstanceBean { + private Long moduleId; + private String moduleCode; + private String propertyCode; + private Object propertyValue; + private List ids; + private String type;//批量编辑:全部更新、清空数据 +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceLink.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceLink.java new file mode 100644 index 0000000..485f9bc --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceLink.java @@ -0,0 +1,45 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/26 17:32 + */ +@Data +public class InstanceLink { + + private Long id; + + private Long relationCategoryId; + + private String relationCategoryCode; + + private Long relationId; + + private String relationName; + + private Long sourceModuleId; + + private String sourceModuleCode; + + private Long sourceInstanceId; + + private String sourceInstanceName; + + private Long targetModuleId; + + private String targetModuleCode; + + private Long targetInstanceId; + + private String targetInstanceName; + + private String sourceType; + + private String targetType; + + private String type; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceModel.java new file mode 100644 index 0000000..e692a3c --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceModel.java @@ -0,0 +1,29 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/6/1 19:35 + */ +@Data +public class InstanceModel { + + private Long moduleId; + + private String moduleCode; + + /** + * 实例关系数据-源实例id + */ + private Long instanceId; + + /** + * 实例关系数据-源实例name + */ + private String instanceName; + + private String iconImage; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceNodeModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceNodeModel.java new file mode 100644 index 0000000..210827d --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceNodeModel.java @@ -0,0 +1,35 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/6/1 17:08 + */ +@Data +public class InstanceNodeModel { + + private Long sourceModuleId; + + private Long targetModuleId; + + /** + * 实例关系数据-源实例id + */ + private Long sourceInstanceId; + /** + * 实例关系数据-目的实例id + */ + private Long targetInstanceId; + + /** + * 实例关系数据-源实例name + */ + private String sourceInstanceName; + /** + * 实例关系数据-目的实例name + */ + private String targetInstanceName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryAlterModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryAlterModel.java new file mode 100644 index 0000000..f219728 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryAlterModel.java @@ -0,0 +1,31 @@ +package com.bocloud.ams.entity.model; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import lombok.Data; + +import java.util.List; + +/** + * @Description: 关联历史调和记录详细信息(props信息) + * @Author majiali + * @CreateTime 2022/6/8 14:33 + */ +@Data +public class InstanceRelationHistoryAlterModel { + + /** + * @Description: 变更后 + * @param null + * @Author majiali + * @CreateTime 2022/6/17 18:27 + */ + private InstanceRelation after; + /** + * @Description: 变更前 + * @param null + * @Author majiali + * @CreateTime 2022/6/17 18:27 + */ + private List before; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryPreflightModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryPreflightModel.java new file mode 100644 index 0000000..11260df --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationHistoryPreflightModel.java @@ -0,0 +1,27 @@ +package com.bocloud.ams.entity.model; + +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import lombok.Data; + +import java.util.List; + +/** + * @Description: 关联历史预检结果 + * @Author majiali + * @CreateTime 2022/6/8 14:33 + */ +@Data +public class InstanceRelationHistoryPreflightModel { + + /** + * 预检结果类型 SUCCESS:成功-可以更新覆盖 FAILED:失败-数据矛盾,视作失败处理 RECONCILED:调和-historyRecordList中数据单选 + */ + private String status; + + private List historyRecordList; + + private String sourceType; + + private String targetType; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationModel.java new file mode 100644 index 0000000..30418ab --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceRelationModel.java @@ -0,0 +1,37 @@ +package com.bocloud.ams.entity.model; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import lombok.Data; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/6/2 14:07 + */ +@Data +public class InstanceRelationModel { + private Long id; + private Long relationCategoryId; + private String relationCategoryCode; + private Long relationId; + private String relationName; + private Long sourceModuleId; + private String sourceModuleCode; + private Long sourceInstanceId; + private String sourceInstanceName; + private Long targetModuleId; + private String targetModuleCode; + private Long targetInstanceId; + private String targetInstanceName; + private List cmdbInstanceRelations; + + /** + * 实例之间的关系 与 模型定义之间的关系 是否一致 + * false 是一致 ; true 是相反 + */ + private Boolean isReversed = false; + private String type; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceTopo.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceTopo.java new file mode 100644 index 0000000..a88fff7 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/InstanceTopo.java @@ -0,0 +1,18 @@ +package com.bocloud.ams.entity.model; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import lombok.Data; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/26 17:30 + */ +@Data +public class InstanceTopo { + List nodes; + List links; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleLink.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleLink.java new file mode 100644 index 0000000..de350ad --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleLink.java @@ -0,0 +1,34 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @Description: + * @Author majiali + * @CreateTime 2022/5/12 13:41 + */ +@Data +public class ModuleLink { + + private Long source; + private Long target; + private String type; + private Long relationId; + private String relationName; + /** + * 关联类型code + */ + private String relationCode; + /** + * 拓扑关系ID + */ + private Long relationCategoryId; + + /** + * 是否是反向规则 + */ + private Boolean isReversed = false; + + + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleTopo.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleTopo.java new file mode 100644 index 0000000..a152104 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ModuleTopo.java @@ -0,0 +1,30 @@ +package com.bocloud.ams.entity.model; + +import java.util.List; + +import com.bocloud.ams.entity.module.CiModule; + +import lombok.Data; + +/** + * @Description: 模型拓扑数据 + * @Title: CmdbModuleTopo + * @Author: majiali + * @CreateTime: 2022/5/13 15:43 + */ +@Data +public class ModuleTopo { + List nodes; + List links; + + public ModuleTopo() { + super(); + } + + public ModuleTopo(List nodes, List links) { + super(); + this.nodes = nodes; + this.links = links; + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/NotifyMessage.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/NotifyMessage.java new file mode 100644 index 0000000..a29db50 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/NotifyMessage.java @@ -0,0 +1,128 @@ +package com.bocloud.ams.entity.model; + + +import com.megatron.common.model.RequestContext; + +/** + * 通知消息体 + * + * @author liuyuanyuan + * @since 2022年5月27日 + */ +public class NotifyMessage { + + private String subject; + private String content; + private String emailContent; + private RequestContext context; + + public String getEmailContent() { + return emailContent; + } + + public void setEmailContent(String emailContent) { + this.emailContent = emailContent; + } + + private boolean sendMsg; + private boolean sendEmail; + + /** + * + */ + public NotifyMessage() { + super(); + } + + /** + * @param context + * @param subject + * @param content + * @param sendMsg + * @param sendEmail + */ + public NotifyMessage(RequestContext context, String subject, String content, boolean sendMsg, boolean sendEmail) { + super(); + this.context = context; + this.subject = subject; + this.content = content; + this.sendMsg = sendMsg; + this.sendEmail = sendEmail; + } + + public NotifyMessage(RequestContext context, String subject, String content, String emailContent, boolean sendMsg, + boolean sendEmail) { + super(); + this.context = context; + this.subject = subject; + this.content = content; + this.emailContent = emailContent; + this.sendMsg = sendMsg; + this.sendEmail = sendEmail; + } + + /** + * @return the subject + */ + public String getSubject() { + return subject; + } + + /** + * @param subject the subject to set + */ + public void setSubject(String subject) { + this.subject = subject; + } + + /** + * @return the content + */ + public String getContent() { + return content; + } + + /** + * @param content the content to set + */ + public void setContent(String content) { + this.content = content; + } + + /** + * @return the sendMsg + */ + public boolean isSendMsg() { + return sendMsg; + } + + /** + * @param sendMsg the sendMsg to set + */ + public void setSendMsg(boolean sendMsg) { + this.sendMsg = sendMsg; + } + + /** + * @return the sendEmail + */ + public boolean isSendEmail() { + return sendEmail; + } + + /** + * @param sendEmail the sendEmail to set + */ + public void setSendEmail(boolean sendEmail) { + this.sendEmail = sendEmail; + } + + public RequestContext getContext() { + return context; + } + + public void setContext(RequestContext context) { + this.context = context; + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/OperateParam.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/OperateParam.java new file mode 100644 index 0000000..f8d85c9 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/OperateParam.java @@ -0,0 +1,15 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/6/17 10:22 + */ +@Data +public class OperateParam { + private Long id; + private String action; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PathModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PathModel.java new file mode 100644 index 0000000..24a500a --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PathModel.java @@ -0,0 +1,25 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/27 14:37 + */ +@Data +public class PathModel { + /** + * 有各个节点名称组成的字符串 + */ + private String topologyPathName; + /** + * 有各个节点中id组成的字符串 + */ + private String topologyPath; + /** + * 这个拓扑路径对于起始模型是正向的还是反向的 + */ + private Boolean pathDirection; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PropertyModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PropertyModel.java new file mode 100644 index 0000000..339f725 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/PropertyModel.java @@ -0,0 +1,37 @@ +package com.bocloud.ams.entity.model; + +import java.util.List; + +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyGroup; +import com.megatron.entity.annotations.IgnoreAll; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/9 17:47 + */ +@Data +public class PropertyModel { + @IgnoreAll + private Long moduleId; + @IgnoreAll + private List groups; + @IgnoreAll + private List properties; + + public PropertyModel(Long moduleId, List groups, List properties) { + super(); + this.moduleId = moduleId; + this.groups = groups; + this.properties = properties; + } + + public PropertyModel() { + super(); + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/RequestInstanceTopologyModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/RequestInstanceTopologyModel.java new file mode 100644 index 0000000..3566eba --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/RequestInstanceTopologyModel.java @@ -0,0 +1,20 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/23 15:36 + */ +@Data +public class RequestInstanceTopologyModel { + private Long categoryId; + private Long startModuleId; + private Integer topologyLevel; + private List ignoreModuleId; + private List wayModuleId; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ResponseInstanceTopologyModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ResponseInstanceTopologyModel.java new file mode 100644 index 0000000..9fc39f2 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/ResponseInstanceTopologyModel.java @@ -0,0 +1,20 @@ +package com.bocloud.ams.entity.model; + +import com.megatron.entity.annotations.Column; +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/23 17:23 + */ +@Data +public class ResponseInstanceTopologyModel { + private Long categoryId; + private Long startModuleId; + private String startModuleCode; + private String startModuleName; + private Long instanceId; + private String instanceName; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/Role.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/Role.java new file mode 100644 index 0000000..8cf2431 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/Role.java @@ -0,0 +1,33 @@ +package com.bocloud.ams.entity.model; + +public class Role { + + private Long id; // ID + private Long tenantId; // 租户ID + private boolean checked; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public boolean isChecked() { + return checked; + } + + public void setChecked(boolean checked) { + this.checked = checked; + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/SearchConfigModel.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/SearchConfigModel.java new file mode 100644 index 0000000..7cfe4a6 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/SearchConfigModel.java @@ -0,0 +1,49 @@ +package com.bocloud.ams.entity.model; + +import java.util.List; +import java.util.Map; + +import lombok.Data; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: { label: '应用系统名称', value: 'name', type: 'Select', data: [{ name: '', id: '' }] } + * @date 2022/5/19 11:06 + */ +@Data +public class SearchConfigModel { + /** + * 模型id + */ + private Long moduleId; + /** + * 搜索项名称 + */ + private String label; + /** + * 搜索项key + */ + private String value; + /** + * 搜索框类型 + */ + private String type; + /** + * 搜索项的下来框数据[{ name: '', id: '' }] + */ + private List> data; + + public SearchConfigModel() { + super(); + } + + public SearchConfigModel(Long moduleId, String label, String value, String type) { + super(); + this.moduleId = moduleId; + this.label = label; + this.value = value; + this.type = type; + } + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/StartModeParams.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/StartModeParams.java new file mode 100644 index 0000000..e241d5c --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/StartModeParams.java @@ -0,0 +1,17 @@ +package com.bocloud.ams.entity.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class StartModeParams { + + @JsonProperty("start_mode") + private String startMode; + + public String getStartMode() { + return startMode; + } + + public void setStartMode(String startMode) { + this.startMode = startMode; + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskBean.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskBean.java new file mode 100644 index 0000000..be70d0b --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskBean.java @@ -0,0 +1,19 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 18:04 + * @Description: + */ +@Data +public class TaskBean { + private Long id; + private String name; + private String remark; + private String graph; + private String code; + private String cron; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskGraph.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskGraph.java new file mode 100644 index 0000000..f8e7b6e --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskGraph.java @@ -0,0 +1,35 @@ +package com.bocloud.ams.entity.model; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 15:05 + * @Description: + */ +@Data +public class TaskGraph { + private String content; + private String collectionType; + private Long timeout; + private String category; + private String target; + private String params; + private String jdbcUrl; + private String database; + private String username; + private String password; + private String method; + private String format; + private String url; + private String headers; + private String body; + + @Override + public String toString() { + return JSONObject.toJSONString(this); + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskInstanceBean.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskInstanceBean.java new file mode 100644 index 0000000..ff06823 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskInstanceBean.java @@ -0,0 +1,32 @@ +package com.bocloud.ams.entity.model; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.megatron.common.utils.DateSerializer; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @Author liuyuanyuan + * @Date 2022/6/13 0013 21:00 + * @Description: + */ +@Data +public class TaskInstanceBean { + private Long id; + private String output; + private String status; + + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date gmtModify; + + @JsonSerialize(using = DateSerializer.class) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss:SSS") + private Date collectionFinish; + + private Double collectionTime; + private String collectionStatus; + private Date gmtFinish; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskNode.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskNode.java new file mode 100644 index 0000000..f03dad5 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskNode.java @@ -0,0 +1,17 @@ +package com.bocloud.ams.entity.model; + +import lombok.Data; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 15:08 + * @Description: + */ +@Data +public class TaskNode { + private String name; + private String code; + private String config; + private String input; + private String control; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskTransferParams.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskTransferParams.java new file mode 100644 index 0000000..937cd48 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/model/TaskTransferParams.java @@ -0,0 +1,24 @@ +package com.bocloud.ams.entity.model; + +public class TaskTransferParams { + + private String cron; + + private Boolean isNew; + + public String getCron() { + return cron; + } + + public void setCron(String cron) { + this.cron = cron; + } + + public Boolean getIsNew() { + return isNew; + } + + public void setNew(Boolean aNew) { + this.isNew = aNew; + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/CiModule.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/CiModule.java new file mode 100644 index 0000000..41dd18e --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/CiModule.java @@ -0,0 +1,40 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author 胡立伟 + * @Date 2022/4/29 0029 16:31 + * @Description: + */ +@Data +@Table("ci_module") +@EqualsAndHashCode(callSuper = true) +public class CiModule extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("module_group_id") + private Long groupId; + @Column("code") + private String code; + @Column("name_space") + private String nameSpace; + @Column("icon_image") + private String iconImage; + @Column("is_disabled") + private Boolean disabled; + @Column("is_reserved") + private Boolean reserved; + @IgnoreAll + private int instanceNum; + //当前模型所属分组的父分组id + @IgnoreAll + private Long parentGroupId; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleGroup.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleGroup.java new file mode 100644 index 0000000..1410cbb --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleGroup.java @@ -0,0 +1,42 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/4/29 0029 14:57 + * @Description: + */ +@Data +@Table("ci_module_group") +@EqualsAndHashCode(callSuper = true) +public class ModuleGroup extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("parent_id") + private Long parentId; + @Column("code") + private String code; + @Column("name_space") + private String nameSpace; + @IgnoreAll + private List modules; + @IgnoreAll + private List childrenGroups; + @IgnoreAll + private Boolean existNextData; + /** + * 当前分组中模型个数 + */ + @IgnoreAll + private Integer count; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleRelation.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleRelation.java new file mode 100644 index 0000000..3ef0cef --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/ModuleRelation.java @@ -0,0 +1,85 @@ +package com.bocloud.ams.entity.module; + +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/5/6 0006 20:42 + * @Description: + */ +@Data +@Table("ci_module_relation") +@EqualsAndHashCode(callSuper = true) +public class ModuleRelation extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + @Column("source_id") + private Long sourceId; + @Column("source_type") + private String sourceType; + @Column("source_code") + private String sourceCode; + @Column("target_type") + private String targetType; + @Column("relation_id") + private Long relationId; + @Column("target_id") + private Long targetId; + @Column("target_code") + private String targetCode; + /** + * @Description: 关联类型分组id + */ + @Column("relation_category_id") + private Long relationCategoryId; + + @Column("relation_category_code") + private String relationCategoryCode; + + @IgnoreAll + private String relationName; + @IgnoreAll + private String relationCategoryName; + /** + * 关联类型code + */ + @IgnoreAll + private String relationCode; + + @IgnoreAll + private Boolean isReversed = false; + + @IgnoreAll + private List ruleItemList; + + @IgnoreAll + private List cmdbModuleRelationList; + + @IgnoreAll + private String sourceName; + + @IgnoreAll + private String targetName; + + @IgnoreAll + private String relationReverseName; + + @IgnoreAll + private String rule; + + @IgnoreAll + private Long moduleId; + + @IgnoreAll + private String iconImage; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Property.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Property.java new file mode 100644 index 0000000..bc75225 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Property.java @@ -0,0 +1,224 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.List; + +@Table("ci_property") +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class Property extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + + @IgnoreAll + private Long propertyId; + + /** + * 所属模型id + */ + @Column("module_id") + private Long moduleId; + /** + * 属性池ID + */ + @Column("property_pool_id") + private Long propertyPoolId; + /** + * 唯一编码 + */ + @Column("code") + private String code; + /** + * 类型 + */ + @Column("type") + private String type; + /** + * 所属分组 + */ + @Column("group_name") + private String groupName; + /** + * 最小值 + */ + @Column("min_value") + private Integer minValue; + /** + * 最大值 + */ + @Column("max_value") + private Integer maxValue; + /** + * 最大长度 + */ + @Column("length") + private Integer length; + /** + * 是否必填 + */ + @Column("is_required") + private Boolean isRequired=false; + + /** + * 默认值类型 + */ + @Column("default_value_type") + private String defaultValueType; + /** + * 默认值 + */ + @Column("default_value") + private String defaultValue; + /** + * 是否唯一 + */ + @Column("is_uniqued") + private Boolean isUniqued=false; + /** + * 排序数 + */ + @Column("order_num") + private Integer orderNum; + /** + * 小数位数 + */ + @Column("decimal_num") + private Integer decimalNum; + /** + * 单位 + */ + @Column("unit") + private String unit; + /** + * 校验id + */ + @Column("regexp_id") + private Long regexpId; + /** + * 0:用户定义 1:系统内置 + */ + @Column("is_reserved") + private Boolean isReserved=false; + /** + * 是否自动采集 + */ + @Column("is_auto_discovery") + private Boolean isAutoDiscovery=false; + /** + * 列表项 + */ + @Column("is_title") + private Boolean isTitle = false; + /** + * 只读 + */ + @Column("is_only_reader") + private Boolean isOnlyReader; + /** + * 是否是搜索项 + */ + @Column("is_search") + private Boolean isSearch=false; + /** + * 规定json格式 + */ + @Column("json_schema") + private String jsonSchema; + /** + * 前缀标识 + */ + @Column("prefix_identifier") + private String prefixIdentifier; + /** + * 起始值 + */ + @Column("start_num") + private Integer startNum; + + /** + * 是否是主键 + */ + @Column("is_key_property") + private Boolean isKeyProperty; + + /** + * 表格类型属性结构体定义类型 0:新建定义 1:从已有模型中引入 + */ + @Column("table_type") + private String tableType; + + /** + * 表格类型属性引入已有模型的模型ID + */ + @Column("link_module_id") + private Long linkModuleId; + + /** + * 表格类型属性引入已有模型的属性id,以逗号隔开 + */ + @Column("property_ids") + private String propertyIds; + + @IgnoreAll + private List itemList; + + @IgnoreAll + private RegularExpression regularExpression; + + public Integer getTableLength(){ + return this.length==null?255:this.length; + } + + public boolean equalTable(Property cmdbProperty) { + if (!this.getCode().equals(cmdbProperty.getCode())) { + return false; + } + if(!this.getTableLength().equals(cmdbProperty.getTableLength())){ + return false; + } + return true; + } + + public Property(String code, String name, String type, String groupName, int length, Boolean required, + Boolean uniqued, int orderNum, Long moduleId, Boolean reserved, Boolean autoDiscovery, Boolean title, + Long creatorId, String defaultValueType, String defaultValue, Boolean isOnlyReader, Boolean isSearch) { + super(); + this.code = code; + super.setName(name); + this.type = type; + this.groupName = groupName; + this.length = length; + //是否必填 + this.isRequired = required; + //是否唯一 + this.isUniqued = uniqued; + this.orderNum = orderNum; + this.moduleId = moduleId; + //0:用户定义 1:系统内置 + this.isReserved = reserved; + this.isAutoDiscovery = autoDiscovery; + //列表项 + this.isTitle = title; + this.defaultValueType = defaultValueType; + this.defaultValue = defaultValue; + //只读 + this.isOnlyReader = isOnlyReader; + //是否是搜索项 + this.isSearch = isSearch; + super.setCreatorId(creatorId); + super.setMenderId(creatorId); + super.setGmtCreate(new Date()); + super.setGmtModify(new Date()); + } +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyGroup.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyGroup.java new file mode 100644 index 0000000..b2108e8 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyGroup.java @@ -0,0 +1,34 @@ +package com.bocloud.ams.entity.module; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Table("ci_property_group") +@Data +@EqualsAndHashCode(callSuper = true) +public class PropertyGroup extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + /** + * 排序 + */ + @Column("order_num") + private Integer orderNum; + /** + * 所属配置模型 + */ + @Column("module_id") + private Long moduleId; + + /** + * 0:用户定义 1:系统内置 + */ + @Column("is_reserved") + private Boolean isReserved=false; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyItem.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyItem.java new file mode 100644 index 0000000..01630ba --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyItem.java @@ -0,0 +1,72 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +@Table("ci_property_item") +@Data +@EqualsAndHashCode(callSuper = true) +public class PropertyItem extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + /** + * 类型 + */ + @Column("value") + private String value; + + /** + * 结构项ID + */ + @Column("code") + private String code; + + /** + * 所属属性id + */ + @Column("property_id") + private Long propertyId; + /** + * 所属模型id + */ + @Column("module_id") + private Long moduleId; + + /** + * TEXTFIELD:单行文本 + * TEXTAREA:多行文本 + * SELECTREDIO:下拉单选 + * SELECTCHECKBOX:下拉多选 + * DATE:日期 + * TIME:时间 + * TEXTENCRYPT:数据加密 + * INTEGER:整数 + * FLOAT:小数 + * JSON:json + * BOOLEAN:布尔值 + * ci_property_pool_item.type + */ + @Column("type") + private String type = "TEXTFIELD"; + + /** + * 表格属性中结构项数据的下拉选项数据 + */ + @Column("item_value") + private String itemValue; + + /** + * itemValue 转化成 集合 + */ + @IgnoreAll + private List itemList; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPool.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPool.java new file mode 100644 index 0000000..89c4b80 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPool.java @@ -0,0 +1,180 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Description: cmdb属性池 + * @Author majiali + * @CreateTime 2022/5/5 14:02 + */ +@Data +@Table("ci_property_pool") +@EqualsAndHashCode(callSuper = true) +public class PropertyPool extends GenericEntity { + @PK(value = PKStrategy.AUTO) + private Long id; + + @Column("code") + private String code; + + /** + * 0:用户定义 1:系统内置 + */ + @Column("is_reserved") + private Boolean isReserved = false; + + /** + * TEXTFIELD:单行文本 + * TEXTAREA:多行文本 + * SINGLESELECT:下拉单选 + * MULTISELECT:下拉多选 + * QUOTE:引用 + * DATE:日期 + * TIME:时间 + * TEXTENCRYPT:数据加密 + * INTEGER:整数 + * FLOAT:小数 + * SINGLELINETABLE:单行表格 + * MULTILINETABLE:多行表格 + * JSON:json + * BOOLEAN:布尔值 + */ + @Column("type") + private String type; + + @Column("json_schema") + private String jsonSchema; + + /** + * 最小值 + */ + @Column("min_value") + private Integer minValue; + + /** + * 最大值 + */ + @Column("max_value") + private Integer maxValue; + + /** + * 默认值类型 固定值:FIXED 内置函数:INNERFUN 自增ID:AUTOINCRID 流水号:SERIALNUM + */ + @Column("default_value_type") + private String defaultValueType; + + /** + * 前缀标识 + */ + @Column("prefix_identifier") + private String prefixIdentifier; + + /** + *内置函数:INNERFUN 只支持 全局唯一标识符对应GLOBALLYUNIQUEIDENTIFIER + * 流水号:SERIALNUM 默认长度为1,存到默认值中 + * + */ + @Column("default_value") + private String defaultValue; + + /** + * 起始值 + */ + @Column("start_num") + private Integer startNum; + + /** + * 最大长度 + */ + @Column("length") + private Integer length; + + /** + * 小数位数 + */ + @Column("decimal_num") + private Integer decimalNum; + + /** + * 0:可为空,1:必填 + */ + @Column("is_required") + private Boolean isRequired = false; + + /** + * 是否唯一 0:不唯一,1:唯一 + */ + @Column("is_uniqued") + private Boolean isUniqued = false; + + /** + * 是否只读 0:否,1:是 + */ + @Column("is_only_reader") + private Boolean isOnlyReader = false; + + /** + * 是否搜索项 0:否,1:是 + */ + @Column("is_search") + private Boolean isSearch = false; + + /** + * 单位 + */ + @Column("unit") + private String unit; + + /** + * 校验规则ID + */ + @Column("regexp_id") + private Long regexpId; + + /** + * 表格类型属性结构体定义类型 0:新建定义 1:从已有模型中引入 + */ + @Column("table_type") + private String tableType; + + /** + * 表格类型属性引入已有模型的模型ID + */ + @Column("link_module_id") + private Long linkModuleId; + + /** + * 表格类型属性引入已有模型的属性id,以逗号隔开 + */ + @Column("property_ids") + private String propertyIds; + + /** + * 列表项 + */ + @Column("is_title") + private Boolean isTitle = false; + + /** + * @Description: 校验规则表达式 + */ + @IgnoreAll + private String expression; + + @IgnoreAll + private List itemList; + + @IgnoreAll + private List propertyList; + + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPoolItem.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPoolItem.java new file mode 100644 index 0000000..86d2a21 --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/PropertyPoolItem.java @@ -0,0 +1,91 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @Description: cmdb属性池配置项 + * 表格项: name:结构项名称 value:结构项ID type:值类型 prop:枚举值 + * 下拉选择: name:属性 value:属性值 + * @Author majiali + * @CreateTime 2022/5/5 14:02 + */ +@Data +@Table("ci_property_pool_item") +@EqualsAndHashCode(callSuper = true) +public class PropertyPoolItem extends GenericEntity { + /** + * 主键ID + * ci_property_pool_item.id + */ + @PK(value = PKStrategy.AUTO) + private Long id; + + /** + * 所属属性池id + * ci_property_pool_item.property_pool_id + */ + @Column("property_pool_id") + private Long propertyPoolId; + + + /** + * + * ci_property_pool_item.code + */ + @Column("code") + private String code; + + /** + * + * ci_property_pool_item.value + */ + @Column("value") + private String value; + + /** + * TEXTFIELD:单行文本 + * TEXTAREA:多行文本 + * SELECTREDIO:下拉单选 + * SELECTCHECKBOX:下拉多选 + * DATE:日期 + * TIME:时间 + * TEXTENCRYPT:数据加密 + * INTEGER:整数 + * FLOAT:小数 + * JSON:json + * BOOLEAN:布尔值 + * ci_property_pool_item.type + */ + @Column("type") + private String type = "TEXTFIELD"; + + /** + * 引入模型中的属性id + */ + @IgnoreAll + private Long propertyId; + + /** + * 引入模型id + */ + @IgnoreAll + private Long moduleId; + + @Column("item_value") + private String itemValue; + + /** + * 表格属性枚举值 + */ + @IgnoreAll + private List itemList; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RegularExpression.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RegularExpression.java new file mode 100644 index 0000000..ba324cc --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RegularExpression.java @@ -0,0 +1,34 @@ +package com.bocloud.ams.entity.module; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * ci_regular_expression实体类 + * @author sunke + * @Version 1.0 + * @since 2020年4月7日 + */ +@Table("ci_regular_expression") +@Data +@EqualsAndHashCode(callSuper = true) +public class RegularExpression extends GenericEntity { + + @PK(value = PKStrategy.AUTO) + private Long id; + + @Column("code") + private String code; + + @Column("expression") + private String expression; + + @Column("message") + private String message; +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Relation.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Relation.java new file mode 100644 index 0000000..02722fc --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/Relation.java @@ -0,0 +1,58 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Description: cmdb关系类型 + * @Author majiali + * @CreateTime 2022/5/5 14:02 + */ +@Data +@Table("ci_relation") +@EqualsAndHashCode(callSuper = true) +public class Relation extends GenericEntity { + /** + * 主键ID + */ + @PK(value = PKStrategy.AUTO) + private Long id; + + /** + * 关系类型分类(拓扑)ID + */ + @Column("category_id") + private Long categoryId; + + @Column("code") + private String code; + /** + * 反向名称 + */ + @Column("reverse_name") + private String reverseName; + + /** + * 0:用户定义 1:系统内置 + */ + @Column("is_reserved") + private Boolean isReserved = false; + /** + * 0:启用 1:停用 + */ + @Column("is_disabled") + private Boolean isDisabled = false; + + /** + * 分组-拓扑名称 + */ + @IgnoreAll + private String categoryName; + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RelationCategory.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RelationCategory.java new file mode 100644 index 0000000..a35afef --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/RelationCategory.java @@ -0,0 +1,43 @@ +package com.bocloud.ams.entity.module; + + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Description: cmdb关联类型分组 + * @Author majiali + * @CreateTime 2022/5/5 14:02 + */ +@Data +@Table("ci_relation_category") +@EqualsAndHashCode(callSuper = true) +public class RelationCategory extends GenericEntity { + /** + * 主键ID + */ + @PK(value = PKStrategy.AUTO) + private Long id; + + @Column("code") + private String code; + + + /** + * '0:启用 1:停用', + */ + @Column("is_reserved") + private Boolean isReserved = false; + /** + * '0:用户定义 1:系统内置', + */ + @Column("is_disabled") + private Boolean isDisabled = false; + + +} diff --git a/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/TopologyConfig.java b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/TopologyConfig.java new file mode 100644 index 0000000..4bd8d6b --- /dev/null +++ b/bocloud.ams.entity/src/main/java/com/bocloud/ams/entity/module/TopologyConfig.java @@ -0,0 +1,120 @@ +package com.bocloud.ams.entity.module; + +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.IgnoreAll; +import com.megatron.entity.annotations.PK; +import com.megatron.entity.annotations.Table; +import com.megatron.entity.bean.GenericEntity; +import com.megatron.entity.meta.PKStrategy; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/12 17:16 + */ +@Table("ci_topology_config") +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class TopologyConfig extends GenericEntity { + + /** + * 主键ID + */ + @PK(value = PKStrategy.AUTO) + private Long id; + + /** + * 拓扑图分组id + */ + @Column("category_id") + private Long categoryId; + + @IgnoreAll + private String categoryName; + + /** + * 起始模型id + */ + @Column("start_module_id") + private Long startModuleId; + + @IgnoreAll + private String startModuleName; + + /** + * 拓扑层级 (是不包括起始层级的) + */ + @Column("topology_level") + private Integer topologyLevel; + + /** + * 忽略模型id集合 + */ + @Column("ignore_module_ids") + private String ignoreModuleIds; + + /** + * 忽略模型可能是多选 + */ + @IgnoreAll + private List ignoreModuleId; + + /** + * 途径模型id + */ + @Column("way_module_ids") + private String wayModuleIds; + + /** + * 途径模型可能是多选的 + */ + @IgnoreAll + private List wayModuleId; + + /** + * 拓扑路径 + */ + @Column("topology_path") + private String topologyPath; + + @IgnoreAll + private String topologyPathName; + + /** + * 拓扑路径方向:0代表正向;1代表反方向 + */ + @Column("path_direction") + private Boolean pathDirection; + + /** + * 配置类型 + */ + @Column("config_type") + private String configType; + + /** + * 起始类型 + */ + @Column("start_type") + private String startType; + + /** + * 向上层数 + */ + @Column("topology_level_up") + private Integer topologyLevelUp; + + /** + * 向下层数 + */ + @Column("topology_level_down") + private Integer topologyLevelDown; + +} diff --git a/bocloud.ams.repository/.gitignore b/bocloud.ams.repository/.gitignore new file mode 100644 index 0000000..e313482 --- /dev/null +++ b/bocloud.ams.repository/.gitignore @@ -0,0 +1,10 @@ +*/target/* +*/.settings/* +*.classpath +*.project +*.prefs +*.class +*.iml +/.idea/* +*/.svn/* +/target/ diff --git a/bocloud.ams.repository/pom.xml b/bocloud.ams.repository/pom.xml new file mode 100644 index 0000000..5ac3e8f --- /dev/null +++ b/bocloud.ams.repository/pom.xml @@ -0,0 +1,18 @@ + + + + bocloud.ams + com.bocloud + 6.5.0-LTS-SZ + + 4.0.0 + bocloud.ams.repository + + + com.bocloud + bocloud.ams.entity + + + \ No newline at end of file diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/TableLogRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/TableLogRepository.java new file mode 100644 index 0000000..20dd4ed --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/TableLogRepository.java @@ -0,0 +1,28 @@ +package com.bocloud.ams.repository; + +import com.bocloud.ams.entity.TableLog; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * @author majiali + * @date 2023/4/20 + */ +@Repository("tableLogRepository") +public class TableLogRepository extends BasicGenericDao { + public TableLogRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public List query(String templateTable) { + String sql = "select * from ci_table_log a where a.template_table = :templateTable and status='SUCCESS' and is_deleted = 0 "; + List list = this.list(TableLog.class, sql, MapTools.simpleMap("templateTable", templateTable)); + return list; + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemRepository.java new file mode 100644 index 0000000..a03abc4 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemRepository.java @@ -0,0 +1,50 @@ +package com.bocloud.ams.repository.association; + +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 17:18 + * @Description: + */ +@Repository +public class AutoRelationRuleItemRepository extends BasicGenericDao { + + public AutoRelationRuleItemRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean deleteByRuleId(Long ruleId, Long userId) throws Exception { + String sql = + "update ci_auto_relation_rule_item set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where relation_rule_id = :ruleId "; + Map params = MapTools.simpleMap("ruleId", ruleId); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByRuleId(Long ruleId) throws Exception { + String sql = + "select b.name source_field_name,b.code source_field_code,b.type source_field_type, c.name target_field_name, c.code target_field_code,c.type target_field_type, a.* " + + " from ci_auto_relation_rule_item a LEFT JOIN ci_property b ON a.source_field = b.id LEFT JOIN ci_property c ON a.target_field = c.id where a.is_deleted=0 and a.relation_rule_id = :ruleId "; + return this.list(AutoRelationRuleItem.class, sql, MapTools.simpleMap("ruleId", ruleId)); + } + + public AutoRelationRuleItem query(Long id) throws Exception { + String sql = "select * from ci_auto_relation_rule_item where id = :id"; + List list = this.list(AutoRelationRuleItem.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemValueRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemValueRepository.java new file mode 100644 index 0000000..753e258 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleItemValueRepository.java @@ -0,0 +1,45 @@ +package com.bocloud.ams.repository.association; + +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/12 0012 20:05 + * @Description: + */ +@Repository +public class AutoRelationRuleItemValueRepository extends BasicGenericDao { + + public AutoRelationRuleItemValueRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean deleteByRuleId(Long ruleId, Long userId) throws Exception { + String sql = "update ci_auto_relation_rule_item_value set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where relation_rule_id = :ruleId "; + Map params = MapTools.simpleMap("ruleId", ruleId); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByItemId(Long itemId) throws Exception { + String sql = "select * from ci_auto_relation_rule_item_value where is_deleted=0 and item_id = :itemId "; + return this.list(AutoRelationRuleItemValue.class, sql, MapTools.simpleMap("itemId", itemId)); + } + + public List queryAllByItemId(Long itemId) throws Exception { + String sql = "select a.*,if(a.source_module_id is not null ,sp.code,spi.code) source_field_code," + " if(a.target_module_id is not null ,tp.code,tpi.code) target_field_code," + " if(a.source_module_id is not null ,sp.name,spi.name) source_field_name," + " if(a.target_module_id is not null ,tp.name,tpi.name) target_field_name ," + " if(a.source_module_id is not null ,sp.type,spi.type) source_field_type," + " if(a.target_module_id is not null ,tp.type,tpi.type) target_field_type " + " from ci_auto_relation_rule_item_value a " + " left join ci_property sp on a.source_property_id =sp.id and sp.is_deleted =0 " + " left join ci_property tp on a.target_property_id =tp.id and tp.is_deleted =0 " + " left join ci_property_item spi on a.source_property_id = spi.id and spi.is_deleted =0 " + " left join ci_property_item tpi on a.target_property_id = tpi.id and tpi.is_deleted =0 " + " where a.is_deleted=0 and a.item_id = :itemId"; + return this.list(AutoRelationRuleItemValue.class, sql, MapTools.simpleMap("itemId", itemId)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleRepository.java new file mode 100644 index 0000000..037340f --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/association/AutoRelationRuleRepository.java @@ -0,0 +1,107 @@ +package com.bocloud.ams.repository.association; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 16:49 + * @Description: + */ +@Repository +public class AutoRelationRuleRepository extends BasicGenericDao { + public AutoRelationRuleRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List queryByModuleRelationIds(List ids) throws Exception { + String sql = "select * from ci_auto_relation_rule where is_deleted=0 and module_relation_id in(:ids) "; + return this.list(AutoRelationRule.class, sql, MapTools.simpleMap("ids", ids)); + } + + public List list(Pager pager) throws Exception { + String sql = "select b.name source_module_name,c.name target_module_name,d.name cmdb_relation_category_name, e.name cmdb_relation_name, a.* from ci_auto_relation_rule a LEFT JOIN ci_module b ON a.source_module_id = b.id LEFT JOIN ci_module c ON a.target_module_id = c.id LEFT JOIN ci_relation_category d ON a.relation_category_id = d.id LEFT JOIN ci_module_relation e ON a.module_relation_id = e.id where a.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(AutoRelationRule.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.id,a.name from ci_auto_relation_rule a where 1=1"; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(AutoRelationRule.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (AutoRelationRule rule : list) { + beans.add(new SimpleBean(rule.getId(), rule.getName())); + } + return beans; + } + + public AutoRelationRule query(Long id) throws Exception { + String sql = "select * from ci_auto_relation_rule where is_deleted=0 and id = :id"; + List list = this.list(AutoRelationRule.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_auto_relation_rule where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, ""); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public int countSameName(String name) throws Exception { + String sql = "select count(1) from ci_auto_relation_rule where is_deleted=0 and name = :name "; + return this.countQuery(sql, MapTools.simpleMap("name", name)).intValue(); + } + + public int isOnly(Long relationCategoryId, Long sourceModuleId, Long targetModuleId) throws Exception { + String sql = "select count(1) from ci_auto_relation_rule where is_deleted=0 and relation_category_id = :relationCategoryId and source_module_id =:sourceModuleId and target_module_id = :targetModuleId "; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + return this.countQuery(sql, params).intValue(); + } + + public AutoRelationRule query(Long relationCategoryId, Long sourceModuleId, Long targetModuleId) throws Exception { + String sql = "select * from ci_auto_relation_rule where is_deleted=0 and relation_category_id = :relationCategoryId and source_module_id =:sourceModuleId and target_module_id = :targetModuleId "; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + List list = this.list(AutoRelationRule.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_auto_relation_rule set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public AutoRelationRule queryByModuleRelationId(Long moduleRelationId) throws Exception { + String sql = "select * from ci_auto_relation_rule where is_deleted=0 and module_relation_id = :moduleRelationId"; + List list = this.list(AutoRelationRule.class, sql, MapTools.simpleMap("moduleRelationId", moduleRelationId)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByModuleIdAndCategoryId(Long moduleId, Long relationCategoryId) throws Exception { + String sql = "select a.* from ci_auto_relation_rule a where a.is_deleted=0 and a.relation_category_id = :relationCategoryId and (a.source_module_id= :moduleId or a.target_module_id = :moduleId) order by a.gmt_modify desc"; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("moduleId", moduleId); + return this.list(AutoRelationRule.class, sql, params); + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditBakRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditBakRepository.java new file mode 100644 index 0000000..c2e3887 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditBakRepository.java @@ -0,0 +1,143 @@ +package com.bocloud.ams.repository.audit; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.audit.OperationalAuditBak; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/23 0023 17:47 + * @Description: + */ +@Repository +public class OperationalAuditBakRepository extends BasicGenericDao { + + public OperationalAuditBakRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public void batchSaveOperationalAuditBak(List audits, String tableName, Integer batchSize) { + synchronized (OperationalAuditBak.class) { + CmdbUtils.changeTableAnnotationValue(OperationalAuditBak.class, tableName); + this.batchSave(audits, batchSize, false); + } + } + + public int countTable(String tableName) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :tableName;"; + Map params = MapTools.simpleMap("tableName", tableName); + return this.countQuery(sql, params).intValue(); + } + + public void createTable(String operationalAuditTable, OperationalAuditBak operationalAudit) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + operationalAuditTable + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(operationalAudit); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL AUTO_INCREMENT,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " NOT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " DEFAULT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } + + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } + + + public int queryCount(String tableName, String leftTime, String rightTime) throws Exception { + String sql = "select count(1) from " + tableName + " a where a.is_deleted = 0 and a.gmt_create >= :leftTime and a.gmt_create <= :rightTime "; + Map params = new HashMap<>(); + params.put("leftTime", leftTime); + params.put("rightTime", rightTime); + return this.countQuery(sql, params).intValue(); + } + + public int count(List params, List finalInstanceTableNames) throws Exception { + String sql = ""; + if (finalInstanceTableNames.size() == 1) { + sql = "select count(1) from " + finalInstanceTableNames.get(0) + " b where b.is_deleted = 0"; + } else { + sql = "select count(1) from ("; + for (int i = 0; i < finalInstanceTableNames.size(); i++) { + if (i > 0) { + sql += " union all "; + } + sql += "(select * from " + finalInstanceTableNames.get(i) + " a where a.is_deleted = 0 )"; + + } + sql += ") b where 1=1 "; + } + sql = getQueryBuilder().buildRaw(sql, params, null, "b"); + Map paramMap = getQueryBuilder().getParam(params); + return this.countQuery(sql, paramMap).intValue(); + } + + public List list(Pager pager, List finalInstanceTableNames) throws Exception { + + String sql = ""; + if (finalInstanceTableNames.size() == 1) { + sql = "select * from " + finalInstanceTableNames.get(0) + " b where b.is_deleted = 0"; + } else { + sql = "select * from ("; + for (int i = 0; i < finalInstanceTableNames.size(); i++) { + if (i > 0) { + sql += " union all "; + } + sql += "(select * from " + finalInstanceTableNames.get(i) + " a where a.is_deleted = 0 )"; + + } + sql += ") b where 1=1 "; + } + + sql = getQueryBuilder().buildRaw(sql, pager, "b"); + + return this.list(OperationalAuditBak.class, sql); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditRepository.java new file mode 100644 index 0000000..eb7a82e --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/audit/OperationalAuditRepository.java @@ -0,0 +1,76 @@ +package com.bocloud.ams.repository.audit; + +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * @Author liuyuanyuan + * @Date 2022/5/23 0023 17:47 + * @Description: + */ +@Repository +public class OperationalAuditRepository extends BasicGenericDao { + + public OperationalAuditRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_operational_audit where is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, ""); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List list(Pager pager) throws Exception { + String sql = "select * from ci_operational_audit where is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, pager, null); + return this.list(OperationalAudit.class, sql); + } + + public OperationalAudit query(Long id) throws Exception { + String sql = "select * from ci_operational_audit where is_deleted=0 and id = :id"; + List list = this.list(OperationalAudit.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List list(List params) throws Exception { + String sql = "select * from ci_operational_audit a where 1 = 1"; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map paramMap = getQueryBuilder().getParam(params); + return this.list(OperationalAudit.class, sql, paramMap); + } + + public List list(List params, int rows) throws Exception { + String sql = "select * from ci_operational_audit a where 1 = 1"; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, rows, params, new HashMap<>()), "a"); + Map paramMap = getQueryBuilder().getParam(params); + return this.list(OperationalAudit.class, sql, paramMap); + } + + public boolean delete(List ids) { + String sql = "delete from ci_operational_audit where id in (:ids)"; + Map params = MapTools.simpleMap("ids", ids); + return this.execute(sql, params) > 0; + } + + public List listTime(List params) throws Exception { + String sql = "select distinct left(gmt_create,7) as dateStr from ci_operational_audit a where 1 = 1"; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map paramMap = getQueryBuilder().getParam(params); + return this.list(OperationalAudit.class, sql, paramMap); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionComponentRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionComponentRepository.java new file mode 100644 index 0000000..95b4d65 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionComponentRepository.java @@ -0,0 +1,98 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 14:28 + * @Description: + */ +@Repository +public class CollectionComponentRepository extends BasicGenericDao { + + public CollectionComponentRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public List list(int page, int rows, List params, Map sorter) throws Exception { + String sql = "select ccc.*,cm.name as module_name, cp.name as property_name from ci_collection_component ccc left join ci_module cm on ccc.module_id = cm.id left join ci_property cp on ccc.property_id = cp.id where ccc.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(page, rows, params, sorter), "ccc"); + return this.list(CollectionComponent.class, sql, getQueryBuilder().getParam(params)); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.id,a.name from ci_collection_component a where a.is_deleted=0"; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(CollectionComponent.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (CollectionComponent component : list) { + beans.add(new SimpleBean(component.getId(), component.getName())); + } + return beans; + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_collection_component a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public CollectionComponent query(Long id) throws Exception { + String sql = "select * from ci_collection_component where id = :id and is_deleted = 0"; + List list = this.list(CollectionComponent.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByTemplateId(Long id) throws Exception { + String sql = "select ccc.*,cm.name as module_name, cp.name as property_name from ci_collection_component ccc left join ci_module cm on ccc.module_id = cm.id left join ci_property cp on cp.id = ccc.property_id where ccc.template_id = :id and ccc.is_deleted = 0 "; + return this.list(CollectionComponent.class, sql, MapTools.simpleMap(Common.ID, id)); + } + + public List queryByTemplateId(Long id, String types, String parameterType) throws Exception { + String sql = "select * from ci_collection_component where template_id = :id and type in(:type) and is_deleted = 0"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("type", types); + if (null != parameterType) { + sql += " and parameter_type = :parameterType "; + params.put("parameterType", parameterType); + } + return this.list(CollectionComponent.class, sql, params); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_collection_component set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean deleteByTemplate(Long id, Long userId) throws Exception { + String sql = "update ci_collection_component set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where template_id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByModuleId(Long moduleId) throws Exception { + String sql = "select * from ci_collection_component where module_id = :moduleId and is_deleted = 0"; + return this.list(CollectionComponent.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryBakRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryBakRepository.java new file mode 100644 index 0000000..4b95a07 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryBakRepository.java @@ -0,0 +1,77 @@ +package com.bocloud.ams.repository.collection; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionHistoryBak; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +/** + * @author huliwei + * @date 2023/4/25 + */ +@Repository("collectionHistoryBakRepository") +public class CollectionHistoryBakRepository extends BasicGenericDao { + public CollectionHistoryBakRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public int countTable(String tableName) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :tableName;"; + Map params = MapTools.simpleMap("tableName", tableName); + return this.countQuery(sql, params).intValue(); + } + + public void createTable(String tableName, CollectionHistoryBak collectionHistoryBak) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + tableName + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(collectionHistoryBak); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL ,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " NOT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " DEFAULT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemBakRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemBakRepository.java new file mode 100644 index 0000000..7c6b074 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemBakRepository.java @@ -0,0 +1,77 @@ +package com.bocloud.ams.repository.collection; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionHistoryItemBak; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +/** + * @author huliwei + * @date 2023/4/25 + */ +@Repository("collectionHistoryItemBakRepository") +public class CollectionHistoryItemBakRepository extends BasicGenericDao { + public CollectionHistoryItemBakRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public int countTable(String tableName) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :tableName;"; + Map params = MapTools.simpleMap("tableName", tableName); + return this.countQuery(sql, params).intValue(); + } + + public void createTable(String tableName, CollectionHistoryItemBak collectionHistoryItemBak) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + tableName + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(collectionHistoryItemBak); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL ,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " NOT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if (null != fieldDBType) { + sqlBuilder.append(" " + fieldDBType + " DEFAULT NULL,\n"); + } else { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemRepository.java new file mode 100644 index 0000000..3cd04a1 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryItemRepository.java @@ -0,0 +1,69 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + + +/** + * @Author yangzhenrong + * @Date 2022/6/15 20:37 + * @Version 1.0 + **/ +@Repository +public class CollectionHistoryItemRepository extends BasicGenericDao { + + public CollectionHistoryItemRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from (select a.*,cp.name as property_name from ci_collection_history_item a left join ci_property cp on a.property_id = cp.id) a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(CollectionHistoryItem.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from (select a.*,cp.name as property_name from ci_collection_history_item a left join ci_property cp on a.property_id = cp.id) a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List listByHistoryId(Long historyId) throws Exception { + String sql = "select a.* from ci_collection_history_item a where a.history_id = :historyId"; + return this.list(CollectionHistoryItem.class, sql, MapTools.simpleMap("historyId", historyId)); + } + + public List listByHistoryIds(List historyIds) throws Exception { + String sql = "select a.* from ci_collection_history_item a where a.history_id in (:historyIds) "; + return this.list(CollectionHistoryItem.class, sql, MapTools.simpleMap("historyIds", historyIds)); + } + + public boolean deleteByHistoryIds(List historyIds) { + String sql = "delete from ci_collection_history where history_id in (:historyIds)"; + Map params = MapTools.simpleMap("historyIds", historyIds); + return this.execute(sql, params) > 0; + } + + public List list(String tableName, Pager pager) throws Exception { + String sql = "select a.* from (select a.*,cp.name as property_name from " + tableName + " a left join ci_property cp on a.property_id = cp.id) a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(CollectionHistoryItem.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(String tableName, List params) throws Exception { + String sql = "select count(1) from (select a.*,cp.name as property_name from " + tableName + " a left join ci_property cp on a.property_id = cp.id) a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryRepository.java new file mode 100644 index 0000000..4175cde --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionHistoryRepository.java @@ -0,0 +1,92 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionHistory; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + + +/** + * @ClassName: CollectionHistoryRepository + * @Description + * @Author yangzhenrong + * @Date 2022/6/15 20:37 + * @Version 1.0 + **/ +@Repository +public class CollectionHistoryRepository extends BasicGenericDao { + + public CollectionHistoryRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List queryByIdAndType(Long taskInstanceId, String type) throws Exception { + String sql = "select a.* from ci_collection_history a where a.task_instance_id = :taskInstanceId and a.type = :type "; + Map params = MapTools.simpleMap("taskInstanceId", taskInstanceId); + params.put("type", type); + return list(CollectionHistory.class, sql, params); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_collection_history a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(CollectionHistory.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_collection_history a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public CollectionHistory query(Long id) throws Exception { + String sql = "select a.* from ci_collection_history a where a.id = :id "; + List list = this.list(CollectionHistory.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List listByTaskInstanceId(Long taskInstanceId) throws Exception { + String sql = "select a.* from ci_collection_history a where a.task_instance_id = :taskInstanceId"; + return this.list(CollectionHistory.class, sql, MapTools.simpleMap("taskInstanceId", taskInstanceId)); + } + + public List listByInstances(List instanceIds) throws Exception { + String sql = "select a.* from ci_collection_history a where a.task_instance_id in (:instanceIds) "; + return this.list(CollectionHistory.class, sql, MapTools.simpleMap("instanceIds", instanceIds)); + } + + public boolean deleteByInstanceIds(List instanceIds) { + String sql = "delete from ci_collection_history where instance_id in (:instanceIds)"; + Map params = MapTools.simpleMap("instanceIds", instanceIds); + return this.execute(sql, params) > 0; + } + + public List queryByIdAndType(String tableName, Long taskInstanceId, String type) throws Exception { + String sql = "select a.* from " + tableName + " a where a.task_instance_id = :taskInstanceId and a.type = :type "; + Map params = MapTools.simpleMap("taskInstanceId", taskInstanceId); + params.put("type", type); + return list(CollectionHistory.class, sql, params); + } + + public int count(String tableName, List params) throws Exception { + String sql = "select count(1) from " + tableName + " a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List list(String tableName, Pager pager) throws Exception { + String sql = "select a.* from " + tableName + " a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(CollectionHistory.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceBakRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceBakRepository.java new file mode 100644 index 0000000..033cfd9 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceBakRepository.java @@ -0,0 +1,79 @@ +package com.bocloud.ams.repository.collection; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionTaskInstanceBak; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +/** + * @author huliwei + * @date 2023/4/25 + */ +@Repository("collectionTaskInstanceBakRepository") +public class CollectionTaskInstanceBakRepository extends BasicGenericDao { + public CollectionTaskInstanceBakRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public int countTable(String tableName) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :tableName;"; + Map params = MapTools.simpleMap("tableName", tableName); + return this.countQuery(sql, params).intValue(); + } + + public void createTable(String tableName, CollectionTaskInstanceBak collectionTaskInstanceBak) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + tableName + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(collectionTaskInstanceBak); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL ,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if(null != fieldDBType){ + sqlBuilder.append(" " + fieldDBType + " NOT NULL,\n"); + }else{ + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + String fieldDBType = fieldJSON.getString("fieldDBType"); + if(null != fieldDBType){ + sqlBuilder.append(" " + fieldDBType + " DEFAULT NULL,\n"); + }else{ + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + //创建表的同时创建索引 + sqlBuilder.append(", index "+ tableName +"_gmt_create (gmt_create)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceRepository.java new file mode 100644 index 0000000..da41787 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskInstanceRepository.java @@ -0,0 +1,122 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.*; + +/** + * @Author liuyuanyuan + * @Date 2022/6/13 0013 16:06 + * @Description: + */ +@Repository +public class CollectionTaskInstanceRepository extends BasicGenericDao { + + public CollectionTaskInstanceRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public boolean updateStatus(Long id, String status) throws Exception { + String sql = "update ci_collection_task_instance set status = :status, gmt_modify = :gmtModify , gmt_finish = :gmtFinish where id = :id and is_deleted=0 "; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("status", status); + params.put("gmtModify", new Date()); + params.put("gmtFinish", new Date()); + return this.execute(sql, params) > 0; + } + + public List list(int page, int rows, List params, Map sorter) throws Exception { + // String sql = "select cti.*, cct.module_id as module_id, cm.code as module_code from + // ci_collection_task_instance cti left join ci_co // cm on cct.module_id = cm.id where cti.is_deleted = 0 ";llection_task cct on cti.task_id = cct.id left join ci_module + String sql = "select cti.id,cti.name,cti.type,cti.status,cti.is_deleted,cti.gmt_create,cti.gmt_modify,cti.creator_id,cti.mender_id,cti.uuid,cti.code,cti.timeout,cti.graph,cti.cron,cti.task_id,cti.gmt_finish,cti.finish_time,cti.input,cti.collection_finish,cti.collection_time,cti.collection_status, cct.module_id as module_id, cm.code as module_code from ci_collection_task_instance cti left join ci_collection_task cct on cti.task_id = cct.id left join ci_module cm on cct.module_id = cm.id where cti.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(page, rows, params, sorter), "cti"); + return this.list(CollectionTaskInstance.class, sql, getQueryBuilder().getParam(params)); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.id,a.name from ci_collection_task_instance a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(CollectionTaskInstance.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (CollectionTaskInstance instance : list) { + beans.add(new SimpleBean(instance.getId(), instance.getName())); + } + return beans; + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_collection_task_instance a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List list(List params) throws Exception { + String sql = "select * from ci_collection_task_instance a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map param = getQueryBuilder().getParam(params); + return this.list(CollectionTaskInstance.class, sql, param); + } + + public CollectionTaskInstance query(Long id) throws Exception { + String sql = "select * from ci_collection_task_instance where id = :id and is_deleted = 0"; + List list = this.list(CollectionTaskInstance.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public CollectionTaskInstance queryByTaskId(String taskId) throws Exception { + String sql = "select * from ci_collection_task_instance where uuid = :uuid and is_deleted = 0"; + List list = this.list(CollectionTaskInstance.class, sql, MapTools.simpleMap(Common.UUID, taskId)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean delete(List ids) { + String sql = "delete from ci_collection_task_instance where id in (:ids)"; + Map params = MapTools.simpleMap("ids", ids); + return this.execute(sql, params) > 0; + } + + public List query(String taskInstanceBakName, String leftTime, String rightTime) throws Exception { + String sql = "select id from " + taskInstanceBakName + " a where a.is_deleted = 0 and a.gmt_create >= :leftTime and a.gmt_create <= :rightTime "; + Map params = new HashMap<>(); + params.put("leftTime", leftTime); + params.put("rightTime", rightTime); + List list = this.list(CollectionTaskInstance.class, sql, params); + return list; + } + + public List list(Pager pager, String taskInstanceBakName) throws Exception { + String sql = "select cti.id,cti.name,cti.type,cti.status,cti.is_deleted,cti.gmt_create,cti.gmt_modify,cti.creator_id,cti.mender_id,cti.uuid,cti.code,cti.timeout,cti.graph,cti.cron,cti.task_id,cti.gmt_finish,cti.finish_time,cti.input,cti.collection_finish,cti.collection_time,cti.collection_status, cct.module_id as module_id, cm.code as module_code , '" + taskInstanceBakName + "' AS table_name from " + taskInstanceBakName + " cti left join ci_collection_task cct on cti.task_id = cct.id left join ci_module cm on cct.module_id = cm.id where cti.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "cti"); + return this.list(CollectionTaskInstance.class, sql); + } + + public List listIdBak(List params, Map sorter, String taskInstanceBakName) throws Exception { + String sql = "select cti.id , '" + taskInstanceBakName + "' AS table_name from " + taskInstanceBakName + " cti where cti.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, params, sorter, "cti"); + return this.list(CollectionTaskInstance.class, sql); + } + + public int count(List params, String taskInstanceBakName) throws Exception { + String sql = "select count(*) from " + taskInstanceBakName + " a where a.is_deleted = 0"; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map paramMap = getQueryBuilder().getParam(params); + return this.countQuery(sql, paramMap).intValue(); + } + + public CollectionTaskInstance query(Long id, String tableName) throws Exception { + String sql = "select * , '" + tableName + "' as table_name from " + tableName + " where id = :id and is_deleted = 0"; + List list = this.list(CollectionTaskInstance.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskRepository.java new file mode 100644 index 0000000..ebc2e99 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTaskRepository.java @@ -0,0 +1,112 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionTask; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 17:06 + * @Description: + */ +@Repository +public class CollectionTaskRepository extends BasicGenericDao { + public CollectionTaskRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public List list(int page, int rows, List params, Map sorter) + throws Exception { + String sql = + "select cct.*,c.name as template_name, cm.name as module_name from ci_collection_task cct left join ci_collection_template c on cct.template_id = c.id left join ci_module cm on cct.module_id = cm.id where cct.is_deleted = 0 and cm.status = 'ENABLE' "; + sql = getQueryBuilder().buildRaw(sql, new Pager(page, rows, params, sorter), "cct"); + return this.list(CollectionTask.class, sql, getQueryBuilder().getParam(params)); + } + + public List list(List params, Map sorter) throws Exception { + String sql = + "select a.id,a.name from ci_collection_task a left join ci_module b on a.module_id = b.id where b.status ='ENABLE' and a.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(CollectionTask.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (CollectionTask task : list) { + beans.add(new SimpleBean(task.getId(), task.getName())); + } + return beans; + } + + public int count(List params) throws Exception { + String sql = + "select count(1) from ci_collection_task a left join ci_module b on a.module_id = b.id where b.status ='ENABLE' and a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public CollectionTask query(Long id) throws Exception { + String sql = "select * from ci_collection_task where id = :id and is_deleted = 0"; + List list = this.list(CollectionTask.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByTemplateId(Long templateId) throws Exception { + String sql = "select * from ci_collection_task where template_id = :templateId and is_deleted = 0"; + return this.list(CollectionTask.class, sql, MapTools.simpleMap("templateId", templateId)); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = + "update ci_collection_task set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean exists(String name, String type) throws Exception { + String sql = "select * from ci_collection_task a where a.is_deleted = 0 and a.name = :name"; + Map params = MapTools.simpleMap("name", name); + if (!StringUtils.isEmpty(type)) { + sql += " and a.type = :type"; + params.put("type", type); + } + List list = this.list(CollectionTask.class, sql, params); + return !list.isEmpty(); + } + + public List findAllByRunning(String status) { + String sql = "select a.* from ci_collection_task a where a.status =:status and a.is_deleted = 0"; + return this.list(CollectionTask.class, sql, MapTools.simpleMap("status", status)); + } + + public Integer changeStatus(Long id, String status, Long menderId) { + String sql = + "update ci_collection_task set status =:status , mender_id = :menderId ,gmt_modify = now() where id = :id and is_deleted = 0"; + Map param = MapTools.simpleMap("id", id); + param.put("status", status); + param.put("menderId", menderId); + return this.execute(sql, param); + } + + public List findScriptTaskByModuleId(Long moduleId) { + String sql = + "select c.* from ci_collection_task c,ci_collection_template t where c.template_id =t.id and t.is_deleted =0 and c.is_deleted =0 " + + " and t.collection_type ='script' and t.module_id = :moduleId "; + return this.list(CollectionTask.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTemplateRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTemplateRepository.java new file mode 100644 index 0000000..c4d4079 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/collection/CollectionTemplateRepository.java @@ -0,0 +1,76 @@ +package com.bocloud.ams.repository.collection; + +import com.bocloud.ams.entity.collection.CollectionTemplate; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 14:18 + * @Description: + */ +@Repository +public class CollectionTemplateRepository extends BasicGenericDao { + + public CollectionTemplateRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public boolean exists(String name) { + String sql = "select * from ci_collection_template a where a.is_deleted = 0 and a.name = :name"; + List list = this.list(CollectionTemplate.class, sql, MapTools.simpleMap("name", name)); + return !list.isEmpty(); + } + + public List list(int page, int rows, List params, Map sorter) throws Exception { + String sql = "select cct.*,cm.name as module_name from ci_collection_template cct left join ci_module cm on cct.module_id = cm.id where cct.is_deleted = 0 and cm.status = 'ENABLE' "; + sql = getQueryBuilder().buildRaw(sql, new Pager(page, rows, params, sorter), "cct"); + return this.list(CollectionTemplate.class, sql, getQueryBuilder().getParam(params)); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.id,a.name,a.collection_type from ci_collection_template a left join ci_module b on a.module_id = b.id where b.status ='ENABLE' and a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(CollectionTemplate.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (CollectionTemplate template : list) { + beans.add(new SimpleBean(template.getId(), template.getName(), template.getCollectionType())); + } + return beans; + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_collection_template a left join ci_module b on a.module_id = b.id where b.status= 'ENABLE' and a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public CollectionTemplate query(Long id) throws Exception { + String sql = "select cct.*,cm.name as module_name from ci_collection_template cct left join ci_module cm on cct.module_id = cm.id where cct.id = :id and cct.is_deleted = 0 "; + List list = this.list(CollectionTemplate.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_collection_template set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/config/CmdbConfigRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/config/CmdbConfigRepository.java new file mode 100644 index 0000000..6a0bd70 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/config/CmdbConfigRepository.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.repository.config; + +import com.bocloud.ams.entity.config.CmdbConfig; +import com.megatron.common.exception.DataBaseException; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Set; + +/** + * @author majiali + * @date 2023/4/20 + */ +@Repository("cmdbConfigRepository") +public class CmdbConfigRepository extends BasicGenericDao { + + public CmdbConfigRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean modify(CmdbConfig config) throws DataBaseException { + return this.baseUpdate(config); + } + + public CmdbConfig query(Long id) throws DataBaseException { + String sql = "select * from ci_cmdb_config where id = :id"; + List list = this.list(CmdbConfig.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List listAll() throws DataBaseException { + String sql = "select a.* from ci_cmdb_config a"; + return this.list(CmdbConfig.class, sql); + } + + public CmdbConfig queryByCode(String code) throws DataBaseException { + String sql = "select * from ci_cmdb_config where code = :code"; + List list = this.list(CmdbConfig.class, sql, MapTools.simpleMap(Common.CODE, code)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean batchUpdate(List configs, String[] fields) throws DataBaseException { + return this.batchUpdate(configs, fields, configs.size()); + } + + public List listByCodes(Set codes) throws DataBaseException { + String sql = "select * from ci_cmdb_config where code in (:code)"; + return this.list(CmdbConfig.class, sql, MapTools.simpleMap(Common.CODE, codes)); + } + + public List listByCategory(String category) throws DataBaseException { + String sql = "select * from ci_cmdb_config where category = (:category)"; + return this.list(CmdbConfig.class, sql, MapTools.simpleMap("category", category)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceAuthorityRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceAuthorityRepository.java new file mode 100644 index 0000000..fc435fb --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceAuthorityRepository.java @@ -0,0 +1,157 @@ +package com.bocloud.ams.repository.instance; + +import com.bocloud.ams.entity.instance.InstanceAuthority; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author yangzhenrong + * @Date 2022/5/23 18:16 + * @Version 1.0 + **/ +@Repository +public class InstanceAuthorityRepository extends BasicGenericDao { + + public InstanceAuthorityRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(InstanceAuthority.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_instance_authority a where a.is_deleted = 0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public InstanceAuthority query(Long id) throws Exception { + String sql = "select * from ci_instance_authority a where a.id = :id and is_deleted=0 "; + List list = this.list(InstanceAuthority.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean remove(Long id, Long userId) throws Exception { + String sql = "update ci_instance_authority set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean batchRemove(Long moduleId, List instanceIds, Long roleId, Long userId) throws Exception { + String sql = "update ci_instance_authority set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId " + " where module_id = :moduleId and instance_id in (:instanceIds) and role_id = :roleId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceIds", instanceIds); + params.put("roleId", roleId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean remove(Long moduleId, Long instanceId, Long userId) throws Exception { + String sql = "update ci_instance_authority set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId " + " where module_id = :moduleId and instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public InstanceAuthority query(Long moduleId, Long instanceId, Long roleId, Long authUserId, String auth) throws Exception { + String sql = "select * from ci_instance_authority a where is_deleted=0 and a.module_id = :moduleId and a.instance_id = :instanceId " + " and a.role_id = :roleId and a.user_id = :authUserId and a.auths like '%" + auth + "%'"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("roleId", roleId); + params.put("authUserId", authUserId); + List list = this.list(InstanceAuthority.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List listByInstanceId(Long moduleId, Long instanceId) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 and a.module_id = :moduleId and a.instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + return this.list(InstanceAuthority.class, sql, params); + } + + public List listByInstanceId(Long moduleId, Long instanceId, Long roleId) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 and a.module_id = :moduleId and a.instance_id = :instanceId and a.role_id = :roleId"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("roleId", roleId); + return this.list(InstanceAuthority.class, sql, params); + } + + public List listByModuleId(Long moduleId, Long authUserId) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 and a.module_id = :moduleId and a.user_id = :authUserId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("authUserId", authUserId); + return this.list(InstanceAuthority.class, sql, params); + } + + public List listByUserId(Long moduleId, Long instanceId, Long authUserId) throws Exception { + String sql = "select * from ci_instance_authority a where is_deleted=0 and a.module_id = :moduleId and a.instance_id = :instanceId " + " and a.user_id = :authUserId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("authUserId", authUserId); + return this.list(InstanceAuthority.class, sql, params); + } + + public InstanceAuthority queryByAuth(Long moduleId, Long instanceId, Long authUserId, String auth) throws Exception { + String sql = "select * from ci_instance_authority a where is_deleted=0 and a.module_id = :moduleId and a.instance_id = :instanceId " + " and a.user_id = :authUserId and a.auths like '%" + auth + "%'"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("authUserId", authUserId); + List list = this.list(InstanceAuthority.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List listByModuleIdAndAuth(Long moduleId, Long authUserId, String auth) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 and a.module_id = :moduleId " + " and a.user_id = :authUserId and a.auths like '%" + auth + "%'"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("authUserId", authUserId); + return this.list(InstanceAuthority.class, sql, params); + } + + public List listByInstanceId(Long moduleId, List instanceIds, List userIds) throws Exception { + String sql = "select a.* from ci_instance_authority a where a.is_deleted = 0 and a.module_id = :moduleId and a.instance_id in (:instanceIds) and a.user_id in (:userIds)"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceIds", instanceIds); + params.put("userIds", userIds); + return this.list(InstanceAuthority.class, sql, params); + } + + public List queryByAuth(Long moduleId, List instanceIds, Long authUserId, String auth) throws Exception { + String sql = "select * from ci_instance_authority a where is_deleted=0 and a.module_id = :moduleId and a.instance_id in (:instanceIds) " + " and a.user_id = :authUserId and a.auths like '%" + auth + "%'"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceIds", instanceIds); + params.put("authUserId", authUserId); + return this.list(InstanceAuthority.class, sql, params); + } + + public boolean batchRemove(Long moduleId, List instanceIds, Long userId) throws Exception { + String sql = "update ci_instance_authority set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId " + " where module_id = :moduleId and instance_id in (:instanceIds) "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceIds", instanceIds); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceHistoryRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceHistoryRepository.java new file mode 100644 index 0000000..0f65b6c --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceHistoryRepository.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.repository.instance; + +import com.bocloud.ams.entity.instance.InstanceHistory; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + + +/** + * @Author yangzhenrong + * @Date 2022/5/16 16:48 + * @Version 1.0 + **/ +@Repository +public class InstanceHistoryRepository extends BasicGenericDao { + + public InstanceHistoryRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_instance_history a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(InstanceHistory.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_instance_history a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List listByInstanceId(Long moduleId, Long instanceId) throws Exception { + String sql = "select a.* from ci_instance_history a where module_id = :moduleId and instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + return this.list(InstanceHistory.class, sql, params); + } + + public boolean remove(Long moduleId, Long instanceId) throws Exception { + String sql = "delete from ci_instance_history where module_id = :moduleId and instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + return this.execute(sql, params) > 0; + } + + public boolean batchRemove(Long moduleId, List instanceIds) throws Exception { + String sql = "delete from ci_instance_history where module_id = :moduleId and instance_id in (:instanceIds) "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceIds", instanceIds); + return this.execute(sql, params) > 0; + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationHistoryRecordRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationHistoryRecordRepository.java new file mode 100644 index 0000000..0170f98 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationHistoryRecordRepository.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.repository.instance; + +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + + +/** + * @Author majiali + * @Date 2022/6/8 15:49 + * @Version 1.0 + **/ +@Repository +public class InstanceRelationHistoryRecordRepository extends BasicGenericDao { + + public InstanceRelationHistoryRecordRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.*,b.name module_relation_name,c.name relation_category_name from ci_instance_relation_history_record a " + " left join ci_module_relation b on a.module_relation_id =b.id " + " left join ci_relation_category c on a.relation_category_id =c.id " + " where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(InstanceRelationHistoryRecord.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_instance_relation_history_record a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public InstanceRelationHistoryRecord query(Long id) throws Exception { + String sql = "select a.*,b.name module_name from ci_instance_relation_history_record a left join ci_module b on a.module_id =b.id where a.id = :id and a.is_deleted=0 "; + List list = this.list(InstanceRelationHistoryRecord.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByIds(List ids) throws Exception { + String sql = "select * from ci_instance_relation_history_record where id in ( :ids ) and is_deleted = 0"; + return this.list(InstanceRelationHistoryRecord.class, sql, MapTools.simpleMap("ids", ids)); + } + + public List queryByCondition(Long instanceId, Long moduleId, String status, Long moduleRelationId) throws Exception { + String sql = "select a.*,b.name module_name from ci_instance_relation_history_record a left join ci_module b on a.module_id =b.id where a.instance_id = :instanceId and a.module_id = :moduleId and a.status=:status and a.module_relation_id= :moduleRelationId and a.is_deleted = 0 order by a.gmt_create desc"; + Map params = MapTools.simpleMap("instanceId", instanceId); + params.put("moduleId", moduleId); + params.put("status", status); + params.put("moduleRelationId", moduleRelationId); + return this.list(InstanceRelationHistoryRecord.class, sql, params); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationRepository.java new file mode 100644 index 0000000..d35c0d0 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRelationRepository.java @@ -0,0 +1,298 @@ +package com.bocloud.ams.repository.instance; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/16 0016 14:21 + * @Description: + */ +@Slf4j +@Repository +public class InstanceRelationRepository extends BasicGenericDao { + + public InstanceRelationRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public int countTable(String instanceRelationTable) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :instanceRelationTable;"; + return this.countQuery(sql, MapTools.simpleMap("instanceRelationTable", instanceRelationTable)).intValue(); + } + + public void updateOfnameBySourceId(String name, String instanceRelationTable, Long sourceInstanceId, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set gmt_modify = :gmtModify,mender_id=:userId,source_instance_name=:name where source_instance_id = :sourceInstanceId "; + Map params = MapTools.simpleMap("sourceInstanceId", sourceInstanceId); + params.put("name", name); + params.put("gmtModify", new Date()); + params.put("userId", userId); + this.execute(sql, params); + } + + public void updateOfnameByTargetId(String name, String instanceRelationTable, Long targetInstanceId, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set gmt_modify = :gmtModify,mender_id=:userId,target_instance_name=:name where target_instance_id = :targetInstanceId "; + Map params = MapTools.simpleMap("targetInstanceId", targetInstanceId); + params.put("name", name); + params.put("gmtModify", new Date()); + params.put("userId", userId); + this.execute(sql, params); + } + + public void createTable(String instanceRelationTable, InstanceRelation relation) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + instanceRelationTable + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(relation); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL AUTO_INCREMENT,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } + + public void dropTable(String instanceRelationTable) throws Exception { + String sql = "DROP TABLE " + instanceRelationTable; + this.execute(sql, null); + } + + public List query(String instanceTable, Long moduleId) throws Exception { + String sql = "select a.* from " + instanceTable + " a where (a.source_id = :moduleId OR a.target_id = :moduleId) and is_deleted=0 "; + return this.list(InstanceRelation.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public List query(String instanceRelationTable, Long sourceModuleId, Long sourceInstanceId, Long targetModuleId, Long targetInstanceId) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 " + " and source_module_id = :sourceModuleId "; + sql += " and target_module_id = :targetModuleId "; + Map params = MapTools.simpleMap("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + if (null != sourceInstanceId) { + sql += " and source_instance_id = :sourceInstanceId "; + params.put("sourceInstanceId", sourceInstanceId); + } + if (null != targetInstanceId) { + sql += " and target_instance_id = :targetInstanceId "; + params.put("targetInstanceId", targetInstanceId); + } + return this.list(InstanceRelation.class, sql, params); + } + + public InstanceRelation queryById(String instanceRelationTable, Long id) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where id = :id and is_deleted=0 "; + List list = this.list(InstanceRelation.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean remove(Long id, String instanceRelationTable, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByModuleIds(String instanceTable, Long sourceModuleId, Long targetModuleId) throws Exception { + String sql = "select a.* from " + instanceTable + " a where a.source_module_id = :sourceModuleId and a.target_module_id = :targetModuleId and a.is_deleted = 0 "; + Map params = MapTools.simpleMap("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + return this.list(InstanceRelation.class, sql, params); + } + + public InstanceRelation query(String instanceRelationTable, Long sourceModuleId, Long sourceInstanceId, String sourceType, Long targetModuleId, Long targetInstanceId, String targetType) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 " + " and source_module_id = :sourceModuleId and source_instance_id = :sourceInstanceId and source_type = :sourceType " + " and target_module_id = :targetModuleId and target_instance_id = :targetInstanceId and target_type = :targetType "; + Map params = MapTools.simpleMap("sourceModuleId", sourceModuleId); + params.put("sourceInstanceId", sourceInstanceId); + params.put("sourceType", sourceType); + params.put("targetModuleId", targetModuleId); + params.put("targetInstanceId", targetInstanceId); + params.put("targetType", targetType); + List list = this.list(InstanceRelation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public InstanceRelation query(String instanceRelationTable, Long moduleId, Long instanceId) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 " + " and (( source_module_id = :moduleId and source_instance_id = :instanceId ) " + " or ( target_module_id = :moduleId and target_instance_id = :instanceId ))"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + List list = this.list(InstanceRelation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public InstanceRelation querySource(String instanceRelationTable, Long moduleId, Long instanceId, Long targetModuleId) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 " + " and source_module_id = :moduleId and source_instance_id = :instanceId and target_module_id = :targetModuleId"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("targetModuleId", targetModuleId); + List list = this.list(InstanceRelation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public InstanceRelation queryTarget(String instanceRelationTable, Long moduleId, Long instanceId, Long sourceModuleId) throws Exception { + String sql = "select a.* ,'1' is_reversed from " + instanceRelationTable + " a where is_deleted=0 " + " and target_module_id = :moduleId and target_instance_id = :instanceId and source_module_id = :sourceModuleId"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("sourceModuleId", sourceModuleId); + List list = this.list(InstanceRelation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByCondition(String instanceRelationTable, Long sourceModuleId, Long sourceInstanceId, Long targetModuleId, Long targetInstanceId) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 "; + Map params = new HashMap<>(); + if (null != sourceModuleId && 0 != sourceModuleId) { + sql += " and source_module_id = :sourceModuleId"; + params.put("sourceModuleId", sourceModuleId); + } + if (null != sourceInstanceId && 0 != sourceInstanceId) { + sql += " and source_instance_id = :sourceInstanceId "; + params.put("sourceInstanceId", sourceInstanceId); + } + if (null != targetModuleId && 0 != targetModuleId) { + sql += " and target_module_id = :targetModuleId"; + params.put("targetModuleId", targetModuleId); + } + if (null != targetInstanceId && 0 != targetInstanceId) { + sql += " and target_instance_id = :targetInstanceId"; + params.put("targetInstanceId", targetInstanceId); + } + return this.list(InstanceRelation.class, sql, params); + } + + public boolean removeByIds(List ids, String instanceRelationTable, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id in (:ids)"; + Map params = MapTools.simpleMap("ids", ids); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByParams(final String instanceRelationTableName, final List instanceIdList, final List moduleIds, final Long categoryId) throws Exception { + String sql = "select a.* from " + instanceRelationTableName + " a where ( a.source_module_id in (:moduleIds) OR a.target_module_id in (:moduleIds) ) and (a.source_instance_id in (:instanceIdList) OR a.target_instance_id in (:instanceIdList)) and relation_category_id = :categoryId and a.is_deleted = 0 "; + Map params = MapTools.simpleMap("instanceIdList", instanceIdList); + params.put("moduleIds", moduleIds); + params.put("categoryId", categoryId); + return this.list(InstanceRelation.class, sql, params); + } + + public List querySources(String instanceRelationTable, Long moduleId, Long instanceId) throws Exception { + String sql = "select a.*,b.source_type,b.target_type,b.relation_id,b.name relation_name from " + instanceRelationTable + " a " + " left join ci_module_relation b on a.module_relation_id = b.id " + " where a.is_deleted=0 and b.is_deleted=0 " + " and a.source_module_id = :moduleId and a.source_instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + return this.list(InstanceRelation.class, sql, params); + } + + public List queryTargets(String instanceRelationTable, Long moduleId, Long instanceId) throws Exception { + String sql = "select a.*,b.source_type,b.target_type,b.relation_id,b.name relation_name,'1' is_reversed from " + instanceRelationTable + " a " + " left join ci_module_relation b on a.module_relation_id = b.id " + " where a.is_deleted=0 and b.is_deleted=0 " + " and a.target_module_id = :moduleId and a.target_instance_id = :instanceId"; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + return this.list(InstanceRelation.class, sql, params); + } + + public List listReverse(final String instanceRelationTableName, Long categoryId, List sourceInstanceIds, List targetInstanceIds) throws Exception { + String sql = " select a.*, b.relationName relation_name , '1' is_reversed from " + instanceRelationTableName + " a join ( select cmr.* , cr.reverse_name as relationName from ci_module_relation cmr join ci_relation cr on cmr.relation_id = cr.id where cmr.relation_category_id = :categoryId and cr.category_id = :categoryId ) b on a.module_relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.relation_category_id = :categoryId " + " and ( a.source_instance_id in ( :sourceInstanceIds ) or a.target_instance_id in ( :targetInstanceIds ) ) "; + Map params = MapTools.simpleMap("categoryId", categoryId); + params.put("sourceInstanceIds", sourceInstanceIds); + params.put("targetInstanceIds", targetInstanceIds); + return this.list(InstanceRelation.class, sql, params); + } + + public List listForward(final String instanceRelationTableName, Long categoryId, List sourceInstanceIds, List targetInstanceIds) throws Exception { + String sql = "select a.*,b.relationName relation_name from " + instanceRelationTableName + " a join ( select cmr.* , cr.name as relationName from ci_module_relation cmr join ci_relation cr on cmr.relation_id = cr.id where cmr.relation_category_id = :categoryId and cr.category_id = :categoryId ) b on a.module_relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.relation_category_id = :categoryId" + " and ( a.source_instance_id in ( :sourceInstanceIds ) or a.target_instance_id in ( :targetInstanceIds ) ) "; + Map params = MapTools.simpleMap("categoryId", categoryId); + params.put("sourceInstanceIds", sourceInstanceIds); + params.put("targetInstanceIds", targetInstanceIds); + return this.list(InstanceRelation.class, sql, params); + } + + public List listReverseByInstanceIds(final String instanceRelationTableName, Long categoryId, Long moduleId, Long instanceId) throws Exception { + String sql = " select a.*,b.reverse_name relation_name , '1' is_reversed from " + instanceRelationTableName + " a join ( select cmr.* , cr.reverse_name from ci_module_relation cmr join ci_relation cr on cmr.relation_id = cr.id where cmr.relation_category_id = :categoryId and cr.category_id = :categoryId ) b on a.module_relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.target_module_id = :moduleId " + " and a.target_instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("categoryId", categoryId); + return this.list(InstanceRelation.class, sql, params); + } + + public List listForwardByInstanceIds(final String instanceRelationTableName, Long categoryId, Long moduleId, Long instanceId) throws Exception { + String sql = "select a.*,b.name relation_name from " + instanceRelationTableName + " a join ( select cmr.* , cr.reverse_name from ci_module_relation cmr join ci_relation cr on cmr.relation_id = cr.id where cmr.relation_category_id = :categoryId and cr.category_id = :categoryId ) b on a.module_relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.source_module_id = :moduleId " + " and a.source_instance_id = :instanceId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("instanceId", instanceId); + params.put("categoryId", categoryId); + return this.list(InstanceRelation.class, sql, params); + } + + public List queryByInstanceIds(String instanceRelationTable, Long sourceModuleId, List sourceInstanceIds, Long targetModuleId, List targetInstanceIds) throws Exception { + String sql = "select a.* from " + instanceRelationTable + " a where is_deleted=0 " + " and source_module_id = :sourceModuleId "; + sql += " and target_module_id = :targetModuleId "; + Map params = MapTools.simpleMap("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + if (!ListTool.isEmpty(sourceInstanceIds)) { + sql += " and source_instance_id in (:sourceInstanceIds) "; + params.put("sourceInstanceIds", sourceInstanceIds); + } + if (!ListTool.isEmpty(targetInstanceIds)) { + sql += " and target_instance_id in (:targetInstanceIds) "; + params.put("targetInstanceIds", targetInstanceIds); + } + return this.list(InstanceRelation.class, sql, params); + } + + public boolean removeByInstanceId(Long instanceId, Long moduleId, String instanceRelationTable, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId " + " where (source_instance_id = :instanceId and source_module_id = :moduleId) " + " or (target_instance_id = :instanceId and target_module_id = :moduleId)"; + Map params = MapTools.simpleMap("instanceId", instanceId); + params.put("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean batchRemoveByInstanceIds(List instanceIds, Long moduleId, String instanceRelationTable, Long userId) throws Exception { + String sql = "update " + instanceRelationTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId " + " where (source_instance_id in (:instanceIds) and source_module_id = :moduleId) " + " or (target_instance_id in (:instanceIds) and target_module_id = :moduleId)"; + Map params = MapTools.simpleMap("instanceIds", instanceIds); + params.put("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRepository.java new file mode 100644 index 0000000..054eb3a --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceRepository.java @@ -0,0 +1,199 @@ +package com.bocloud.ams.repository.instance; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author yangzhenrong + * @Date 2022/5/11 11:31 + * @Version 1.0 + **/ +@Repository +public class InstanceRepository extends BasicGenericDao { + + public InstanceRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public void createTable(String instanceTable, Instance cmdbInstance) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + instanceTable + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(cmdbInstance); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL AUTO_INCREMENT,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + //实例表名称字段长度和实例值表name长度保持一致 + if ("name".equalsIgnoreCase(fieldName)) { + fieldJSON.put("length", 100); + } + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } + + public void dropTable(String instanceTable) throws Exception { + String sql = "DROP TABLE " + instanceTable; + this.execute(sql, null); + } + + public int countTable(String instanceTable) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :instanceTable;"; + return this.countQuery(sql, MapTools.simpleMap("instanceTable", instanceTable)).intValue(); + } + + public List> list(Pager pager, String instanceTable, String instanceValueTable, Long userId, boolean hasAdminRole) throws Exception { + String moduleId = CmdbUtils.getField(pager.getParams(), "moduleId"); + if (moduleId == null) { + throw new Exception("查询失败"); + } + String sql = buildSql(instanceTable, instanceValueTable, moduleId, userId, hasAdminRole); + sql = "select a.* from (" + sql + ") a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + Map paramMap = getQueryBuilder().getParam(pager.getParams()); + return this.list(sql, paramMap); + } + + public int count(List params, String instanceTable, String instanceValueTable, Long userId, boolean hasAdminRole) throws Exception { + String moduleId = CmdbUtils.getField(params, "moduleId"); + if (moduleId == null) { + throw new Exception("查询失败"); + } + String sql = buildSql(instanceTable, instanceValueTable, moduleId, userId, hasAdminRole); + sql = "select count(1) from (" + sql + ") a where 1=1 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map param = getQueryBuilder().getParam(params); + return this.countQuery(sql, param).intValue(); + } + + public Instance queryByUuid(String instanceTable, String uuid, Long moduleId) throws Exception { + String sql = "select a.* from " + instanceTable + " a where a.uuid = :uuid and module_id = :moduleId and is_deleted=0 "; + Map params = MapTools.simpleMap(Common.UUID, uuid); + params.put("moduleId", moduleId); + List list = this.list(Instance.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByModuleId(String instanceTable, Long moduleId) throws Exception { + String sql = "select a.* from " + instanceTable + " a where module_id = :moduleId and is_deleted=0 "; + return this.list(Instance.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public Instance query(String instanceTable, Long id) throws Exception { + String sql = "select a.* from " + instanceTable + " a where id = :id and is_deleted=0 "; + List list = this.list(Instance.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean remove(Long id, String instanceTable, Long userId) throws Exception { + String sql = "update " + instanceTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + private String buildSql(String instanceTable, String instanceValueTable, String moduleId, Long userId, boolean hasAdminRole) throws Exception { + // 行转列的表头 + String sql = "SELECT GROUP_CONCAT('MAX(IF(P.ID = ',P.id,',INSV.PROPERTY_VALUE,NULL)) AS ''',P.code,'''') as sqlResult" + " from ci_property AS P where P.is_deleted = 0 and P.module_id=" + moduleId; + + List> result = this.list(sql); + if (result == null || result.isEmpty()) { + throw new Exception("查询失败,模型无法使用"); + } + String sqlResult = result.get(0).get("sqlResult").toString(); + + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("SELECT INS.id,INS.module_id,INS.module_code,INS.gmt_create,INS.creator_id"); + if (sqlResult != null && !"".equals(sqlResult)) { + sqlBuilder.append(","); + sqlBuilder.append(sqlResult); + } + sqlBuilder.append(" FROM " + instanceTable + " INS"); + sqlBuilder.append(" LEFT JOIN " + instanceValueTable + " AS INSV ON INS.ID = INSV.instance_id and INSV.is_deleted=0 "); + sqlBuilder.append(" LEFT JOIN ci_property AS P ON INS.module_id = P.module_id and INSV.property_id=P.id "); + if (!hasAdminRole) { + sqlBuilder.append(" LEFT JOIN ci_instance_authority AU on INS.module_id = AU.module_id and INS.id = AU.instance_id"); + } + sqlBuilder.append(" where INS.is_deleted=0 and INS.uuid is not null and INS.module_id=" + moduleId); + if (!hasAdminRole) { + sqlBuilder.append(" and (( AU.auths like '%ACCESS%' and AU.user_id=" + userId + ") or INS.creator_id=" + userId + ")"); + } + sqlBuilder.append(" GROUP BY INS.ID order by INS.id desc"); + return sqlBuilder.toString(); + } + + public List> listAll(String instanceTable, String instanceValueTable, Long moduleId, List ids, Long userId, boolean hasAdminRole) throws Exception { + String sql = buildSql(instanceTable, instanceValueTable, String.valueOf(moduleId), userId, hasAdminRole); + sql = "select a.* from (" + sql + ") a where 1=1 "; + if (null != ids && !ids.isEmpty()) { + sql += "and a.id in (:ids)"; + } + return this.list(sql, MapTools.simpleMap("ids", ids)); + } + + public List queryByModuleId(String instanceTable, String instanceValueTable, Long moduleId, String propertyCode) throws Exception { + String sql = "select a.id,a.uuid,a.module_id,a.module_code,b.property_value name from " + instanceTable + " a left join " + instanceValueTable + " b on a.id = b.instance_id " + " where a.module_id = :moduleId and b.property_code = :propertyCode and a.is_deleted=0 "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("propertyCode", propertyCode); + return this.list(Instance.class, sql, params); + } + + public List queryList(String instanceTable, List ids) throws Exception { + String sql = "select a.* from " + instanceTable + " a where id in (:ids) and is_deleted=0 "; + return this.list(Instance.class, sql, MapTools.simpleMap("ids", ids)); + } + + public boolean batchRemove(List ids, String instanceTable, Long userId) throws Exception { + String sql = "update " + instanceTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id in (:ids)"; + Map params = MapTools.simpleMap("ids", ids); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean deleteById(Long id, String instanceTable) throws Exception { + String sql = "delete from " + instanceTable + " where id = :id"; + return this.execute(sql, MapTools.simpleMap(Common.ID, id)) > 0; + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceValueRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceValueRepository.java new file mode 100644 index 0000000..a9f798b --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/instance/InstanceValueRepository.java @@ -0,0 +1,176 @@ +package com.bocloud.ams.repository.instance; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + + +/** + * @Author yangzhenrong + * @Date 2022/5/11 11:31 + * @Version 1.0 + **/ +@Repository +public class InstanceValueRepository extends BasicGenericDao { + + public InstanceValueRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public void createTable(String instanceValueTable, InstanceValue cmdbInstanceValue) throws Exception { + // 拼接sql + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE " + instanceValueTable + " (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(cmdbInstanceValue); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL AUTO_INCREMENT,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + this.execute(sqlBuilder.toString(), null); + } + + public void dropTable(String instanceValueTable) throws Exception { + String sql = "DROP TABLE " + instanceValueTable; + this.execute(sql, null); + } + + public int countTable(String instanceValueTable) throws Exception { + String sql = "select count(1) from information_schema.TABLES where table_schema = (select database()) AND TABLE_NAME = :instanceValueTable;"; + Map params = MapTools.simpleMap("instanceValueTable", instanceValueTable); + return this.countQuery(sql, params).intValue(); + } + + public List list(Pager pager, String instanceValueTable) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(InstanceValue.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params, String instanceValueTable) throws Exception { + String sql = "select count(1) from " + instanceValueTable + " a where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List listByInstanceId(Long instanceId, String instanceValueTable) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where a.is_deleted=0 and a.instance_id=:instanceId"; + return this.list(InstanceValue.class, sql, MapTools.simpleMap("instanceId", instanceId)); + } + + public boolean remove(Long id, String instanceValueTable, Long userId) throws Exception { + String sql = "update " + instanceValueTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean removeByInstanceId(Long instanceId, String instanceValueTable, Long userId) throws Exception { + String sql = "update " + instanceValueTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where instance_id = :instanceId"; + Map params = MapTools.simpleMap("instanceId", instanceId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean removeByPropertyId(Long propertyId, String instanceValueTable, Long userId) throws Exception { + String sql = "update " + instanceValueTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where property_id = :propertyId "; + Map params = MapTools.simpleMap("propertyId", propertyId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public InstanceValue query(String instanceValueTable, String propertyCode, String propertyValue) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where property_code = :propertyCode and property_value = :propertyValue and is_deleted=0 "; + Map params = MapTools.simpleMap("propertyCode", propertyCode); + params.put("propertyValue", propertyValue); + List list = this.list(InstanceValue.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public InstanceValue query(String instanceValueTable, String propertyCode, Long instanceId) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where property_code = :propertyCode and instance_id = :instanceId and is_deleted=0 "; + Map params = MapTools.simpleMap("propertyCode", propertyCode); + params.put("instanceId", instanceId); + List list = this.list(InstanceValue.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByInstanceIdsAndPropertyIds(String instanceValueTable, List instanceIds, List propertyIds) throws Exception { + final String sql = "select a.* from " + instanceValueTable + " a where a.instance_id in ( :instanceIds ) and a.property_id in ( :propertyIds ) and a.is_deleted = 0 "; + final Map params = MapTools.simpleMap("instanceIds", instanceIds); + params.put("propertyIds", propertyIds); + return this.list(InstanceValue.class, sql, params); + } + + public List listByPropertyCode(String instanceValueTable, String propertyCode) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where a.property_code = :propertyCode and a.is_deleted=0 "; + Map params = MapTools.simpleMap("propertyCode", propertyCode); + return this.list(InstanceValue.class, sql, params); + } + + public List queryByInstanceIds(String instanceTableName, List instanceIdList) { + String sql = "select a.* from " + instanceTableName + " a where a.instance_id in (:instanceIdList) and a.is_deleted = 0 "; + return this.list(InstanceValue.class, sql, MapTools.simpleMap("instanceIdList", instanceIdList)); + } + + public List listAll(String instanceValueTable) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where a.is_deleted=0 "; + return this.list(InstanceValue.class, sql, null); + } + + public boolean batchRemoveByInstanceIds(List instanceIds, String instanceValueTable, Long userId) throws Exception { + String sql = "update " + instanceValueTable + " set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where instance_id in (:instanceIds)"; + Map params = MapTools.simpleMap("instanceIds", instanceIds); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List queryList(String instanceValueTable, String propertyCode, List instanceIds) throws Exception { + String sql = "select a.* from " + instanceValueTable + " a where property_code = :propertyCode and instance_id in (:instanceIds) and is_deleted=0 "; + Map params = MapTools.simpleMap("propertyCode", propertyCode); + params.put("instanceIds", instanceIds); + return this.list(InstanceValue.class, sql, params); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleGroupRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleGroupRepository.java new file mode 100644 index 0000000..4d5f191 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleGroupRepository.java @@ -0,0 +1,73 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.ModuleGroup; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/4/29 0029 16:14 + * @Description: + */ +@Repository +public class ModuleGroupRepository extends BasicGenericDao { + public ModuleGroupRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_module_group set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List queryRoot() throws Exception { + String sql = "select * from ci_module_group where is_deleted =0 and parent_id =0 ORDER BY gmt_create DESC "; + return this.list(ModuleGroup.class, sql, null); + } + + public List queryChildren(Long id) throws Exception { + String sql = "select * from ci_module_group where is_deleted =0 and parent_id = :id ORDER BY gmt_create DESC "; + return this.list(ModuleGroup.class, sql, MapTools.simpleMap("id", id)); + } + + public List all() throws Exception { + String sql = "select * from ci_module_group where is_deleted=0 "; + return this.list(ModuleGroup.class, sql, null); + } + + public int countSameNameOrCode(String name, String code) throws Exception { + String sql = "select count(1) from ci_module_group where is_deleted=0 "; + if (null != code) { + sql += " and code = :code "; + } else if (null != name) { + sql += " and name = :name "; + } + Map params = MapTools.simpleMap("code", code); + params.put("name", name); + return this.countQuery(sql, params).intValue(); + } + + public ModuleGroup query(Long id) throws Exception { + String sql = "select * from ci_module_group a where a.id = :id and is_deleted=0 "; + List list = this.list(ModuleGroup.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByIds(List ids) throws Exception { + String sql = "select * from ci_module_group a where a.id in (:ids) and is_deleted=0 "; + return this.list(ModuleGroup.class, sql, MapTools.simpleMap("ids", ids)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRelationRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRelationRepository.java new file mode 100644 index 0000000..fdfedcf --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRelationRepository.java @@ -0,0 +1,137 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.ModuleRelation; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: 关联关系Dao + * @Author: majiali + * @CreateTime: 2022/5/7 14:03 + */ +@Repository +public class ModuleRelationRepository extends BasicGenericDao { + + public ModuleRelationRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_module_relation set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_module_relation a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(ModuleRelation.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_module_relation a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public ModuleRelation query(Long id) throws Exception { + String sql = "select a.*,sm.name source_name,tm.name target_name,c.name relation_category_name,CONCAT(a.source_type,'-',a.target_type) rule from ci_module_relation a " + " left join ci_module sm on a.source_id =sm.id and sm.is_deleted =0 " + " left join ci_module tm on a.target_id =tm.id and tm.is_deleted =0 " + " left join ci_relation_category c on a.relation_category_id =c.id and c.is_deleted =0 " + " where a.id = :id and a.is_deleted=0 "; + List list = this.list(ModuleRelation.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public ModuleRelation query(Long relationCategoryId, Long sourceModuleId, Long targetModuleId) throws Exception { + String sql = "select a.* from ci_module_relation a where a.relation_category_id = :relationCategoryId and a.source_id = :sourceModuleId and a.target_id = :targetModuleId and is_deleted=0 "; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("sourceModuleId", sourceModuleId); + params.put("targetModuleId", targetModuleId); + List list = this.list(ModuleRelation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.* from ci_module_relation a where is_deleted=0"; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + return this.list(ModuleRelation.class, sql, getQueryBuilder().getParam(params)); + } + + public List list(Long moduleId, Long categoryId) throws Exception { + String sql = "select a.*,b.name relation_name,b.code relation_code from ci_module_relation a join ci_relation b on a.relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.relation_category_id = :categoryId" + " and a.source_id=:moduleId "; + Map params = MapTools.simpleMap("categoryId", categoryId); + params.put("moduleId", moduleId); + return this.list(ModuleRelation.class, sql, params); + } + + public List listReverse(Long moduleId, Long categoryId) throws Exception { + String sql = " select a.*,b.reverse_name relation_name,b.code relation_code,'1' is_reversed from ci_module_relation a join ci_relation b on a.relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.relation_category_id = :categoryId " + " and a.target_id=:moduleId "; + Map params = MapTools.simpleMap("categoryId", categoryId); + params.put("moduleId", moduleId); + return this.list(ModuleRelation.class, sql, params); + } + + public List listByCategoryId(Long categoryId) throws Exception { + String sql = "select a.*,b.name relation_name,b.code relation_code from ci_module_relation a join ci_relation b on a.relation_id=b.id where a.is_deleted = 0 and b.is_deleted=0 and a.relation_category_id = :categoryId"; + return this.list(ModuleRelation.class, sql, MapTools.simpleMap("categoryId", categoryId)); + } + + public List queryModuleRealtionAndModuleImage(Long categoryId) throws Exception { + String sql = "SELECT cm.id as module_id,cm.icon_image, cmr.* FROM ci_module_relation cmr ,ci_module cm WHERE (cmr.source_id =cm.id or cmr .target_id =cm.id) and cmr.is_deleted =0 and cmr.relation_category_id = :categoryId "; + return this.list(ModuleRelation.class, sql, MapTools.simpleMap("categoryId", categoryId)); + } + + public List queryModuleList(Long categoryId) throws Exception { + String sql = "select a.* from ci_module_relation a where a.is_deleted=0 and a.relation_category_id = :categoryId"; + return this.list(ModuleRelation.class, sql, MapTools.simpleMap("categoryId", categoryId)); + } + + public List queryByModuleId(Long moduleId) throws Exception { + String sql = "select a.*, m1.name source_name,m2.name target_name from ci_module_relation a" + " left join ci_module m1 on m1.id=a.source_id " + " left join ci_module m2 on m2.id=a.target_id " + " where a.is_deleted=0 and (a.source_id = :moduleId OR a.target_id = :moduleId) "; + return this.list(ModuleRelation.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public List query(Long relationCategoryId, Long moduleId) throws Exception { + String sql = "select a.* ,r.name relation_name,r.reverse_name relation_reverse_name from ci_module_relation a left join ci_relation r on a.relation_id =r.id where a.is_deleted=0 and a.relation_category_id = :relationCategoryId and (a.source_id = :moduleId OR a.target_id = :moduleId) "; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("moduleId", moduleId); + return this.list(ModuleRelation.class, sql, params); + } + + public boolean deleteByModuleId(Long moduleId, Long userId) throws Exception { + String sql = " update ci_module_relation set is_deleted = 1 , gmt_modify = :gmtModify , mender_id = :userId where source_id = :moduleId or target_id = :moduleId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List listAll() throws Exception { + String sql = "select a.*, m1.name source_name,m2.name target_name from ci_module_relation a" + " left join ci_module m1 on m1.id=a.source_id " + " left join ci_module m2 on m2.id=a.target_id where a.is_deleted=0 "; + return this.list(ModuleRelation.class, sql); + } + + public List queryByRelationId(Long relationId) throws Exception { + String sql = "select a.* from ci_module_relation a where a.is_deleted=0 and a.relation_id = :relationId "; + return this.list(ModuleRelation.class, sql, MapTools.simpleMap("relationId", relationId)); + } + + public List queryAll(Long relationCategoryId, Long moduleId) throws Exception { + String sql = "select a.*,sb.name source_name ,rb.name target_name,r.name relation_name ,r.reverse_name relation_reverse_name from ci_module_relation a,ci_module sb,ci_module rb,ci_relation r " + " where a.is_deleted=0 and a.source_id=sb.id and a.target_id =rb.id and a.relation_id =r.id and a.relation_category_id = :relationCategoryId and (a.source_id = :moduleId OR a.target_id = :moduleId) "; + Map params = MapTools.simpleMap("relationCategoryId", relationCategoryId); + params.put("moduleId", moduleId); + return this.list(ModuleRelation.class, sql, params); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRepository.java new file mode 100644 index 0000000..fd6cef1 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/ModuleRepository.java @@ -0,0 +1,117 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.CiModule; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/5 0005 14:47 + * @Description: + */ +@Repository +public class ModuleRepository extends BasicGenericDao { + + public ModuleRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_module a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(CiModule.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_module a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_module set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where id = :id "; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List existCollectionTemplate(String moduleName) throws Exception { + String sql = "SELECT cm.* FROM ci_module cm WHERE cm.status = 'ENABLE' and cm.is_deleted = 0 AND EXISTS (SELECT * FROM ci_collection_template cct WHERE cct.is_deleted = 0 AND cm.id = cct.module_id) "; + if (null != moduleName) { + sql += " AND cm.name LIKE '%" + moduleName + "%'"; + } + return this.list(CiModule.class, sql, null); + } + + public List existCollectionTask(String moduleName) throws Exception { + String sql = "SELECT cm.* FROM ci_module cm WHERE cm.status = 'ENABLE' and cm.is_deleted = 0 AND EXISTS (SELECT * FROM ci_collection_task cct WHERE cct.is_deleted = 0 AND cm.id = cct.module_id) "; + if (null != moduleName) { + sql += " AND cm.name LIKE '%" + moduleName + "%'"; + } + return this.list(CiModule.class, sql, null); + } + + public List all() throws Exception { + String sql = "select * from ci_module where is_deleted=0 "; + return this.list(CiModule.class, sql, null); + } + + public List queryByGroupId(Long groupId) throws Exception { + String sql = "select * from ci_module where is_deleted=0 and module_group_id = :groupId ORDER BY gmt_create DESC"; + return this.list(CiModule.class, sql, MapTools.simpleMap("groupId", groupId)); + } + + public CiModule query(Long id) throws Exception { + String sql = " select a.* from ci_module a where a.id = :id and a.is_deleted=0 "; + List list = this.list(CiModule.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public int countSameNameOrCode(String name, String code) throws Exception { + String sql = "select count(1) from ci_module where is_deleted=0 "; + if (null != code) { + sql += " and code = :code "; + } else if (null != name) { + sql += " and name = :name "; + } + Map params = MapTools.simpleMap("code", code); + params.put("name", name); + return this.countQuery(sql, params).intValue(); + } + + public List listByIds(List ids) throws Exception { + String sql = "select a.* from ci_module a where a.is_deleted = 0 and a.id in (:ids) "; + return this.list(CiModule.class, sql, MapTools.simpleMap("ids", ids)); + } + + /** + * order by field (id, :ids)按照查询的ids顺序返回数据 + * + * @param ids + * @return + * @throws Exception + */ + public List queryModuleListByIds(List ids) throws Exception { + String sql = "select * from ci_module where is_deleted = 0 and id in (:ids) order by field (id, :ids)"; + return this.list(CiModule.class, sql, MapTools.simpleMap("ids", ids)); + } + + public CiModule queryByCode(String code) throws Exception { + String sql = "select * from ci_module a where a.code = :code and is_deleted=0 "; + List list = this.list(CiModule.class, sql, MapTools.simpleMap("code", code)); + return list.isEmpty() ? null : list.get(0); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyGroupRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyGroupRepository.java new file mode 100644 index 0000000..68f996c --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyGroupRepository.java @@ -0,0 +1,41 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.PropertyGroup; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 12:01 + */ +@Repository +public class PropertyGroupRepository extends BasicGenericDao { + + public PropertyGroupRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean deleteByModuleId(Long moduleId, Long userId) throws Exception { + String sql = "update ci_property_group set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where module_id = :moduleId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List listByModuleId(Long moduleId) { + String sql = "select a.* from ci_property_group a where a.module_id = :moduleId and a.is_deleted = 0"; + return this.list(PropertyGroup.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyItemRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyItemRepository.java new file mode 100644 index 0000000..cd10f57 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyItemRepository.java @@ -0,0 +1,53 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.PropertyItem; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 12:01 + */ +@Repository +public class PropertyItemRepository extends BasicGenericDao { + + public PropertyItemRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean deleteByModuleId(Long moduleId, Long userId) throws Exception { + String sql = "update ci_property_item set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where module_id = :moduleId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List queryByModuleId(Long moduleId) { + String sql = "select a.* from ci_property_item a where a.module_id = :moduleId and a.is_deleted = 0"; + return this.list(PropertyItem.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public List queryByPropertyId(Long propertyId) { + String sql = "select a.* from ci_property_item a where a.property_id = :propertyId and a.is_deleted = 0"; + return this.list(PropertyItem.class, sql, MapTools.simpleMap("propertyId", propertyId)); + } + + public List queryByModuleIdAndPropertyIds(Long moduleId, List propertyIds) { + String sql = "select a.* from ci_property_item a where a.module_id = :moduleId and a.property_id in(:propertyIds) and a.is_deleted = 0"; + Map paramMap = MapTools.simpleMap("propertyIds", propertyIds); + paramMap.put("moduleId", moduleId); + return this.list(PropertyItem.class, sql, paramMap); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolItemRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolItemRepository.java new file mode 100644 index 0000000..65cb239 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolItemRepository.java @@ -0,0 +1,61 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.PropertyPoolItem; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: cmdb属性池配置项 + * @Author: majiali + * @CreateTime: 2022/5/5 14:04 + */ +@Repository +public class PropertyPoolItemRepository extends BasicGenericDao { + public PropertyPoolItemRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_property_pool_item set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean deleteByIds(List ids, Long userId) throws Exception { + String sql = "update ci_property_pool_item set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id in (:ids)"; + Map params = MapTools.simpleMap("ids", ids); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public boolean deleteByPropertyPoolId(Long propertyPoolId, Long userId) throws Exception { + String sql = "update ci_property_pool_item set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where property_pool_id = :propertyPoolId"; + Map params = MapTools.simpleMap("propertyPoolId", propertyPoolId); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List listByPropertyPoolId(Long propertyPoolId) throws Exception { + String sql = "select a.* from ci_property_pool_item a where a.is_deleted=0 and a.property_pool_id = :propertyPoolId"; + return this.list(PropertyPoolItem.class, sql, MapTools.simpleMap("propertyPoolId", propertyPoolId)); + } + + public List listByPropertyPoolIds(List propertyPoolIds) throws Exception { + String sql = "select a.* from ci_property_pool_item a where a.is_deleted=0 and a.property_pool_id in (:propertyPoolIds)"; + return this.list(PropertyPoolItem.class, sql, MapTools.simpleMap("propertyPoolIds", propertyPoolIds)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolRepository.java new file mode 100644 index 0000000..0974a75 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyPoolRepository.java @@ -0,0 +1,72 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.PropertyPool; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: 属性池Dao + * @Author: majiali + * @CreateTime: 2022/5/5 14:03 + */ +@Repository +public class PropertyPoolRepository extends BasicGenericDao { + + public PropertyPoolRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_property_pool set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List list(Pager pager) throws Exception { + String sql = "select a.*,c.expression from ci_property_pool a left join ci_regular_expression c on a.regexp_id=c.id where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(PropertyPool.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_property_pool a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public PropertyPool query(Long id) throws Exception { + String sql = "select a.*,c.expression from ci_property_pool a left join ci_regular_expression c on a.regexp_id=c.id where a.id = :id and a.is_deleted=0 "; + List list = this.list(PropertyPool.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public PropertyPool queryByCode(String code) throws Exception { + String sql = "select a.* from ci_property_pool a where a.code = :code and a.is_deleted=0 "; + List list = this.list(PropertyPool.class, sql, MapTools.simpleMap("code", code)); + return list.isEmpty() ? null : list.get(0); + } + + public List listByPropertyIds(List propertyIds) throws Exception { + String sql = "select a.* from ci_property_pool a,ci_property b where a.is_deleted=0 and a.id=b.property_pool_id" + " and b.is_deleted=0 and b.property_pool_id is not null and b.id in (:propertyIds)"; + return this.list(PropertyPool.class, sql, MapTools.simpleMap("propertyIds", propertyIds)); + } + + public List listByPoolIds(List poolIds) throws Exception { + String sql = " select a.* from ci_property_pool a , ci_property b where a.is_deleted=0 and a.id=b.property_pool_id " + " and b.is_deleted=0 and b.property_pool_id is not null and a.id in (:poolIds) "; + return this.list(PropertyPool.class, sql, MapTools.simpleMap("poolIds", poolIds)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyRepository.java new file mode 100644 index 0000000..5737ae5 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/PropertyRepository.java @@ -0,0 +1,113 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.Property; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 12:01 + */ +@Repository +public class PropertyRepository extends BasicGenericDao { + + public PropertyRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean deleteByModuleId(Long moduleId, Long userId) throws Exception { + String sql = "update ci_property set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where module_id = :moduleId "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("gmtModify", new Date()); + params.put("menderId", userId); + return this.execute(sql, params) > 0; + } + + public List listNotHiddenByCmdbModuleId(Long moduleId) { + // 模型界面显示未隐藏字段 + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.module_id = :moduleId order by a.order_num"; + return this.list(Property.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public Property query(Long id) { + String sql = "select * from ci_property a where a.id = :id and is_deleted=0 "; + List list = this.list(Property.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public Property queryByCode(Long moduleId, String code) throws Exception { + String sql = "select * from ci_property a where a.module_id = :moduleId and a.code = :code and a.is_deleted=0 "; + Map params = MapTools.simpleMap("moduleId", moduleId); + params.put("code", code); + List list = this.list(Property.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public List queryParams(List params, Long moduleId) throws Exception { + String sql = "select * from ci_property a where a.module_id = :moduleId and a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + final Map paramMap = getQueryBuilder().getParam(params); + paramMap.put("moduleId", moduleId); + return this.list(Property.class, sql, paramMap); + } + + public List list(final Pager pager, final Long moduleId) throws Exception { + String sql = "select * from ci_property a where a.module_id = :moduleId and a.is_deleted=0 and a.type not in ('SINGLELINETABLE','MULTILINETABLE') "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + Map paramMap = getQueryBuilder().getParam(pager.getParams()); + paramMap.put("moduleId", moduleId); + return this.list(Property.class, sql, paramMap); + } + + public int count(final List params, final Long moduleId) throws Exception { + String sql = "select count(1) from ci_property a where a.module_id = :moduleId and a.is_deleted=0 and a.type not in ('SINGLELINETABLE','MULTILINETABLE') "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + Map param = getQueryBuilder().getParam(params); + param.put("moduleId", moduleId); + return this.countQuery(sql, param).intValue(); + } + + public List listIsTitleByModuleId(Long moduleId) { + // 模型界面显示未隐藏字段 + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.module_id = :moduleId and is_title = 1 order by a.order_num"; + return this.list(Property.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + public List appointPropertylist(List ids) { + // 模型界面显示未隐藏字段 + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.id in (:ids) order by a.order_num"; + return this.list(Property.class, sql, MapTools.simpleMap("ids", ids)); + } + + // 查询不是引入属性池中的属性信息 + public List queryListNotLink(List ids) { + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.property_pool_id is null and a.id in (:ids) order by a.order_num"; + return this.list(Property.class, sql, MapTools.simpleMap("ids", ids)); + } + + public List queryListByPoolIds(Long propertyPoolId) { + // 模型界面显示未隐藏字段 + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.property_pool_id = :propertyPoolId"; + return this.list(Property.class, sql, MapTools.simpleMap("propertyPoolId", propertyPoolId)); + } + + public List queryByLinkModuleId(Long id) { + // 模型界面显示未隐藏字段 + String sql = "select a.* from ci_property a where a.is_deleted = 0 and a.link_module_id = :id"; + return this.list(Property.class, sql, MapTools.simpleMap("id", id)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RegularExpressionRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RegularExpressionRepository.java new file mode 100644 index 0000000..8093c01 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RegularExpressionRepository.java @@ -0,0 +1,39 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.RegularExpression; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 12:07 + */ +@Repository +public class RegularExpressionRepository extends BasicGenericDao { + + public RegularExpressionRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public RegularExpression query(Long id) { + String sql = "select * from ci_regular_expression a where a.id = :id and is_deleted = 0"; + List list = this.list(RegularExpression.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List listAll() throws Exception { + String sql = "select * from ci_regular_expression where is_deleted = 0"; + return this.list(RegularExpression.class, sql, new HashMap(10)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationCategoryRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationCategoryRepository.java new file mode 100644 index 0000000..29666ab --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationCategoryRepository.java @@ -0,0 +1,79 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.RelationCategory; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: 关联关系分组Dao + * @Author: majiali + * @CreateTime: 2022/5/5 14:03 + */ +@Repository +public class RelationCategoryRepository extends BasicGenericDao { + public RelationCategoryRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_relation_category set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.* from ci_relation_category a where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + return this.list(RelationCategory.class, sql, getQueryBuilder().getParam(params)); + } + + public RelationCategory queryByCode(String code) throws Exception { + String sql = "select a.* from ci_relation_category a where a.code = :code and is_deleted=0 "; + List list = this.list(RelationCategory.class, sql, MapTools.simpleMap("code", code)); + return list.isEmpty() ? null : list.get(0); + } + + public RelationCategory query(Long id) throws Exception { + String sql = "select a.* from ci_relation_category a where a.id = :id and is_deleted=0 "; + List list = this.list(RelationCategory.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_relation_category a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(RelationCategory.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_relation_category a where a.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List listByModuleId(Long moduleId) throws Exception { + String sql = "select a.* from ci_relation_category a where is_deleted = 0 and a.id in (select distinct relation_category_id from ci_module_relation where is_deleted=0 and (source_id = :moduleId OR target_id = :moduleId)) order by a.gmt_modify desc"; + return this.list(RelationCategory.class, sql, MapTools.simpleMap("moduleId", moduleId)); + } + + + public RelationCategory queryByName(String name) throws Exception { + String sql = "select a.* from ci_relation_category a where a.name = :name and is_deleted=0 "; + List list = this.list(RelationCategory.class, sql, MapTools.simpleMap("name", name)); + return list.isEmpty() ? null : list.get(0); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationRepository.java new file mode 100644 index 0000000..4e9deac --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/RelationRepository.java @@ -0,0 +1,82 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.Relation; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @Description: 关联关系Dao + * @Author: majiali + * @CreateTime: 2022/5/7 14:03 + */ +@Repository +public class RelationRepository extends BasicGenericDao { + + public RelationRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate, CurrentService service) { + super(jdbcTemplate, npJdbcTemplate, service); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = "update ci_relation set is_deleted=1,gmt_modify = :gmtModify,mender_id=:userId where id = :id"; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public List list(Pager pager) throws Exception { + String sql = "select a.*,b.name category_name from ci_relation a,ci_relation_category b where a.category_id =b.id and a.is_deleted=0 and b.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(Relation.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public int count(List params) throws Exception { + String sql = "select count(1) from ci_relation a,ci_relation_category b where a.category_id =b.id and a.is_deleted=0 and b.is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List list(List params, Map sorter) throws Exception { + String sql = "select a.* from ci_relation a where is_deleted=0"; + sql = getQueryBuilder().buildRaw(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a"); + List list = this.list(Relation.class, sql, getQueryBuilder().getParam(params)); + List beans = new ArrayList<>(); + for (Relation relation : list) { + beans.add(new SimpleBean(relation.getId(), relation.getName() + "(反向关系名称:" + relation.getReverseName() + ")")); + } + return beans; + } + + public Relation queryByCode(String code, Long categoryId) throws Exception { + String sql = "select a.* from ci_relation a where a.code = :code and is_deleted=0 and category_id = :categoryId"; + Map params = MapTools.simpleMap("code", code); + params.put("categoryId", categoryId); + List list = this.list(Relation.class, sql, params); + return list.isEmpty() ? null : list.get(0); + } + + public Relation query(Long id) throws Exception { + String sql = "select a.* from ci_relation a where a.id = :id and is_deleted=0 "; + List list = this.list(Relation.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public List queryByCategoryId(Long categoryId) throws Exception { + String sql = "select a.* from ci_relation a where a.is_deleted=0 and a.category_id =:categoryId"; + return this.list(Relation.class, sql, MapTools.simpleMap("categoryId", categoryId)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/TopologyConfigRepository.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/TopologyConfigRepository.java new file mode 100644 index 0000000..e1076c4 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/module/TopologyConfigRepository.java @@ -0,0 +1,82 @@ +package com.bocloud.ams.repository.module; + +import com.bocloud.ams.entity.module.TopologyConfig; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.database.core.intf.impl.BasicGenericDao; +import com.megatron.framework.core.CurrentService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/12 17:56 + */ +@Repository +public class TopologyConfigRepository extends BasicGenericDao { + + public TopologyConfigRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate, CurrentService service) { + super(jdbcTemplate, namedParameterJdbcTemplate, service); + } + + public int count(List params) throws Exception { + String sql = " select count(1) from ci_topology_config a where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, params, null, "a"); + return this.countQuery(sql, getQueryBuilder().getParam(params)).intValue(); + } + + public List list(Pager pager) throws Exception { + String sql = "select a.* from ci_topology_config a where is_deleted=0 "; + sql = getQueryBuilder().buildRaw(sql, pager, "a"); + return this.list(TopologyConfig.class, sql, getQueryBuilder().getParam(pager.getParams())); + } + + public TopologyConfig query(Long id) throws Exception { + String sql = "select * from ci_topology_config where is_deleted = 0 and id = :id "; + List list = this.list(TopologyConfig.class, sql, MapTools.simpleMap(Common.ID, id)); + return list.isEmpty() ? null : list.get(0); + } + + public boolean delete(Long id, Long userId) throws Exception { + String sql = " update ci_topology_config set is_deleted = 1 , gmt_modify = :gmtModify , mender_id = :userId where id = :id "; + Map params = MapTools.simpleMap(Common.ID, id); + params.put("gmtModify", new Date()); + params.put("userId", userId); + return this.execute(sql, params) > 0; + } + + public int countSameNameOrCode(String name, Long id, String configType) throws Exception { + String sql = "select count(1) from ci_topology_config where is_deleted = 0 and name = :name "; + final Map params = MapTools.simpleMap("name", name); + if (null != id) { + sql = sql + " and id != :id "; + params.put("id", id); + } + if (StringUtils.isNotEmpty(configType)) { + sql = sql + " and config_type = :configType "; + params.put("configType", configType); + } + return this.countQuery(sql, params).intValue(); + } + + public List listAll() throws Exception { + String sql = "select a.* from ci_topology_config a where is_deleted=0 "; + return this.list(TopologyConfig.class, sql); + } + + public List queryListBycategoryId(Long categoryId) throws Exception { + String sql = "select a.* from ci_topology_config a where is_deleted=0 and a.category_id = :categoryId "; + return this.list(TopologyConfig.class, sql, MapTools.simpleMap("categoryId", categoryId)); + } + +} diff --git a/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/utils/CmdbUtils.java b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/utils/CmdbUtils.java new file mode 100644 index 0000000..85106e1 --- /dev/null +++ b/bocloud.ams.repository/src/main/java/com/bocloud/ams/repository/utils/CmdbUtils.java @@ -0,0 +1,495 @@ +package com.bocloud.ams.repository.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.bocloud.ams.annotation.ColumnType; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.megatron.common.model.Param; +import com.megatron.common.utils.ListTool; +import com.megatron.entity.annotations.Column; +import com.megatron.entity.annotations.Table; + +import lombok.extern.slf4j.Slf4j; + +/** + * @ClassName: CmdbUtils + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 14:56 + * @Version 1.0 + **/ +@Slf4j +public class CmdbUtils { + + public static final String CMDB_INSTANCE = "ci_instance_"; + public static final String CMDB_INSTANCE_VALUE = "ci_instance_value_"; + public static final String CMDB_INSTANCE_RELATION = "ci_instance_relation_"; + + public static final String TYPE_STRING = "java.lang.String"; + public static final String TYPE_LONG = "java.lang.Long"; + public static final String TYPE_BOOLEAN = "java.lang.Boolean"; + public static final String TYPE_DATE = "java.util.Date"; + public static final String TYPE_FLOAT = "java.lang.Float"; + public static final String TYPE_DOUBLE = "java.lang.Double"; + public static final String TYPE_BIGDECIMAL = "java.math.BigDecimal"; + public static final String TYPE_INTEGER = "java.lang.Integer"; + public static final String INSTANCE_RELATION_TYPE_SOURCE = "SOURCE"; + public static final String INSTANCE_RELATION_TYPE_TARGET = "TARGET"; + public static final String CMDB_OPERATIONAL_AUDIT_BAK = "ci_operational_audit_bak_"; + + // 转换数据类型 + public static String judgeDataType(String type) { + switch (type) { + case TYPE_STRING: + return "varchar"; + case TYPE_LONG: + return "bigint"; + case TYPE_BOOLEAN: + return "tinyint"; + case TYPE_DATE: + return "datetime"; + case TYPE_FLOAT: + return "float"; + case TYPE_DOUBLE: + return "double"; + case TYPE_BIGDECIMAL: + return "decimal"; + case TYPE_INTEGER: + return "int"; + default: + return "varchar"; + } + } + + /*** + * 获取对象指定注解Column的相关字段及类型 + * + * @param object + * @return + */ + public static Map getDeclaredFieldsInfo(Object object) { + Map map = new LinkedHashMap<>(); + // 父类属性 + Field[] genericFields = object.getClass().getSuperclass().getDeclaredFields(); + // 属性 + Field[] fields = object.getClass().getDeclaredFields(); + for (Field field : fields) { + boolean annotationColumn = field.isAnnotationPresent(Column.class); + if (annotationColumn) { + String annotationVal = field.getAnnotation(Column.class).value(); + String fieldType = field.getType().getName(); + boolean nullable = field.getAnnotation(Column.class).nullable(); + long length = field.getAnnotation(Column.class).length(); + JSONObject fieldJSON = new JSONObject(); + fieldJSON.put("fieldType", fieldType); + fieldJSON.put("length", length); + fieldJSON.put("nullable", nullable); + boolean columnType = field.isAnnotationPresent(ColumnType.class); + if(columnType){ + String columnTypeValue = field.getAnnotation(ColumnType.class).value(); + fieldJSON.put("fieldDBType", columnTypeValue); + } + map.put(annotationVal, fieldJSON); + } + } + for (Field field : genericFields) { + boolean annotationColumn = field.isAnnotationPresent(Column.class); + if (annotationColumn) { + String annotationVal = field.getAnnotation(Column.class).value(); + String fieldType = field.getType().getName(); + boolean nullable = field.getAnnotation(Column.class).nullable(); + long length = field.getAnnotation(Column.class).length(); + JSONObject fieldJSON = new JSONObject(); + fieldJSON.put("fieldType", fieldType); + fieldJSON.put("length", length); + fieldJSON.put("nullable", nullable); + boolean columnType = field.isAnnotationPresent(ColumnType.class); + if(columnType){ + String columnTypeValue = field.getAnnotation(ColumnType.class).value(); + fieldJSON.put("fieldDBType", columnTypeValue); + } + map.put(annotationVal, fieldJSON); + } + } + return map; + } + // public static Map getDeclaredFieldsInfo(Object object) { + // Map map = new LinkedHashMap<>(); + // //父类属性 + // Field[] genericFields = object.getClass().getSuperclass().getDeclaredFields(); + // //属性 + // Field[] fields = object.getClass().getDeclaredFields(); + // for (Field field : fields) { + // boolean annotationColumn = field.isAnnotationPresent(Column.class); + // if (annotationColumn) { + // String annotationVal = field.getAnnotation(Column.class).value(); + // String fieldType = field.getType().getName(); + // map.put(annotationVal, fieldType); + // } + // } + // for (Field field : genericFields) { + // boolean annotationColumn = field.isAnnotationPresent(Column.class); + // if (annotationColumn) { + // String annotationVal = field.getAnnotation(Column.class).value(); + // String fieldType = field.getType().getName(); + // map.put(annotationVal, fieldType); + // } + // } + // return map; + // } + + /*** + * CmdbInstanceValue数据行转列 + * + * @param list + * @return + */ + public static JSONObject instanceValueRowToCol(List list) { + JSONObject object = new JSONObject(); + if (ListTool.isEmpty(list)) { + return object; + } + Map tempMap = new HashMap<>(); + for (InstanceValue instanceValue : list) { + if (!StringUtils.isEmpty(instanceValue.getPropertyCode())) { + tempMap.put(instanceValue.getPropertyCode(), instanceValue.getPropertyValue()); + } + } + for (Map.Entry entry : tempMap.entrySet()) { + object.put(entry.getKey(), entry.getValue()); + } + return object; + } + + /*** + * 更改Table注解值 + * + * @param clazz + * @param newTableValue + */ + public static void changeTableAnnotationValue(Class clazz, String newTableValue) { + try { + Table tableAnnotation = (Table)clazz.getAnnotation(Table.class); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(tableAnnotation); + // 获取私有 memberValues 属性 + Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues"); + memberValuesField.setAccessible(true); + Map memberValuesValue = (Map)memberValuesField.get(invocationHandler); + // 修改属性值 + memberValuesValue.put("value", newTableValue); + } catch (Exception e) { + log.error("changeTableAnnotationValue fail", e); + } + } + + public static Class changeTableAnnotation(Class clazz, String newTableValue) { + try { + Table tableAnnotation = (Table)clazz.getAnnotation(Table.class); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(tableAnnotation); + // 获取私有 memberValues 属性 + Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues"); + memberValuesField.setAccessible(true); + Map memberValuesValue = (Map)memberValuesField.get(invocationHandler); + // 修改属性值 + memberValuesValue.put("value", newTableValue); + } catch (Exception e) { + log.error("changeTableAnnotation fail", e); + } + return clazz; + } + + /*** + * 判断字符串是否满足正则表达式 + * + * @param regex + * @param source + * @return + */ + public static boolean contains(String regex, String source) { + Pattern pattern = Pattern.compile(regex); + return pattern.matcher(source).find(); + } + + public static boolean isJSON(String str) { + boolean result = false; + try { + Object obj = JSON.parse(str); + result = true; + } catch (Exception e) { + result = false; + } + return result; + } + + public static boolean isDate(String str) { + // 日期格式校验 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + sdf.parse(str); + return true; + } catch (ParseException e) { + return false; + } + } + + public static boolean isTime(String str) { + // 时间格式校验 + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + try { + sdf.parse(str); + return true; + } catch (ParseException e) { + return false; + } + } + + /*** + * 判断是否为布尔型 + * + * @param str + * @return + */ + public static boolean isBool(String str) { + try { + if ("true".equalsIgnoreCase(str) || "0".equals(str) || "false".equalsIgnoreCase(str) || "1".equals(str)) { + return true; + } else { + return false; + } + } catch (Exception e) { + return false; + } + } + + /*** + * 判断是否为数值 + * + * @param str + * @return + */ + public static boolean isNumeric(String str) { + try { + Pattern pattern = Pattern.compile("^(\\-|\\+)?\\d+(\\.\\d+)?$"); + Matcher isNum = pattern.matcher(str); + if (!isNum.matches()) { + return false; + } + return true; + } catch (Exception e) { + return false; + } + } + + /*** + * 从查询参数内获取指定字段的值 + * + * @param params + * @param field + * @return + */ + public static String getField(List params, String field) { + if ((null != params) && (!params.isEmpty())) { + for (Param param : params) { + for (String key : param.getParam().keySet()) { + if (field.equals(key)) { + return param.getParam().get(key).toString(); + } + } + } + } + return null; + } + + /*** + * 带下划线字段转驼峰 + * + * @param name + * @return + */ + public static String toCamelCase(String name) { + if (null == name) { + return null; + } + if (name.contains("_")) { + name = name.toLowerCase(); + StringBuilder sb = new StringBuilder(name.length()); + boolean upperCase = false; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c == '_') { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + return sb.toString(); + } else { + return name; + } + } + + // 判断某个值是否在枚举类中 + public static boolean isInclude(Class enumClass, String value) { + List enumList = EnumUtils.getEnumList(enumClass); + for (int i = 0; i < enumList.size(); i++) { + Object en = enumList.get(i); + Class enClass = en.getClass(); + try { + Method method = enClass.getMethod("getValue"); // 需要与枚举类方法对应 + Object invoke = method.invoke(en, null); + if (invoke.toString().equalsIgnoreCase(value)) { + return true; + } + } catch (Exception e) { + return false; + } + } + return false; + } + + public static void main(String[] args) throws Exception { + // System.out.println(CmdbUtils.isNumeric("22.233333333333333333")); + // System.out.println(CmdbUtils.changeTableAnnotation(CmdbInstanceValue.class, + // "ci_instance_value_alll_in_one")); + + // Object propertyValueJSON = JSON.parse(String.valueOf("[{2: \"2\"}]")); + // System.out.println(propertyValueJSON.toString()); + // System.out.println(CmdbUtils.isInclude(CmdbInstanceEnum.authority.class, "ACCESS")); + // + // System.out.println(CmdbInstanceEnum.authority.valueOf("ACCESS").getName()); + // List> list = new ArrayList<>(); + // Map map = new HashMap<>(); + // map.put("name", "test"); + // map.put("module_id", 5L); + // list.add(map); + // Map map11 = new HashMap<>(); + // map11.put("name", "test6"); + // map11.put("module_id", 6L); + // list.add(map11); + // + // Iterator> iterator = list.iterator(); + // while (iterator.hasNext()) { + // Map map2 = iterator.next(); + // map2.put("eee","eeee"); + //// Iterator> it = map2.entrySet().iterator(); + //// Map newMap = new HashMap<>(); + //// while (it.hasNext()) { + //// Map.Entry entry = it.next(); + //// if ("module_id".equals(entry.getKey())) { + //// newMap.put(entry.getKey(), map2.get(entry.getKey())); + //// it.remove(); + //// } + //// } + //// for (String key : newMap.keySet()) { + //// map2.put(CmdbUtils.toCamelCase(key), newMap.get(key)); + //// + //// } + // } + // System.out.println(JSON.toJSONString(list)); + // System.out.println(JSON.toJSONString(list)); + // System.out.println(InstanceHistory.catalog.INSTANCE); + + // String str = "2022-03-03 12:22"; + // System.out.println(Integer.valueOf(null)); + // System.out.println(Integer.valueOf(0)); + // System.out.println(Integer.valueOf("ddddd")); + + // System.out.println(CmdbUtils.isBool("0")); + + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE TABLE ci_collection_history_item (\n"); + Map fieldMap = CmdbUtils.getDeclaredFieldsInfo(new CollectionHistoryItem()); + // id默认为主键 + sqlBuilder.append("id bigint NOT NULL AUTO_INCREMENT,\n"); + for (Map.Entry entry : fieldMap.entrySet()) { + String fieldName = entry.getKey(); + JSONObject fieldJSON = entry.getValue(); + sqlBuilder.append("" + fieldName + ""); + String fieldType = CmdbUtils.judgeDataType(fieldJSON.getString("fieldType")); + if (!fieldJSON.getBooleanValue("nullable")) { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") NOT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) NOT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " NOT NULL,\n"); + } + } else { + if ("varchar".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(" + fieldJSON.getLong("length") + ") DEFAULT NULL,\n"); + } else if ("tinyint".equals(fieldType)) { + sqlBuilder.append(" " + fieldType + "(1) DEFAULT NULL,\n"); + } else { + // 目前包括bigint、datetime + sqlBuilder.append(" " + fieldType + " DEFAULT NULL,\n"); + } + } + } + sqlBuilder.append("PRIMARY KEY (id)\n"); + sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); + System.out.println(sqlBuilder.toString()); + + // Map lmap = new HashMap(); + // + // List instanceValues=new ArrayList<>(); + // + // for (int i=0;i<10;i++) { + // CmdbModuleInstanceValue instanceValue = new CmdbModuleInstanceValue(); + // instanceValue.setPropertyCode("code" + i); + // instanceValue.setPropertyValue("value" + i); + // instanceValues.add(instanceValue); + // } + // for (CmdbModuleInstanceValue instanceValue:instanceValues){ + // String code=instanceValue.getPropertyCode(); + // String value=instanceValue.getPropertyValue(); + // lmap.put(code,value); + // } + // JSONObject object = new JSONObject(); + // object.put("uuid", "uuid"); + // object.put("instanceId", "instanceId"); + // for (Map.Entry entry : lmap.entrySet()) { + // object.put(entry.getKey(),entry.getValue()); + // } + // System.out.println(object.toJSONString()); + + // try { + // changeTableAnnotationValue(CmdbInstance.class, "essssss"); + // Class cmdbModuleInstanceClass = CmdbInstance.class; + // Table tableAnnotation = cmdbModuleInstanceClass.getAnnotation(Table.class); + //// InvocationHandler invocationHandler = Proxy.getInvocationHandler(tableAnnotation); + //// // 获取私有 memberValues 属性 + //// Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues"); + //// memberValuesField.setAccessible(true); + //// Map memberValuesValue = (Map) memberValuesField.get(invocationHandler); + //// // 修改属性值 + //// memberValuesValue.put("value", "123"); + // + // System.out.println(tableAnnotation.value()); + // + // + // } catch (Exception e) { + // } + + } +} diff --git a/bocloud.ams.service/.gitignore b/bocloud.ams.service/.gitignore new file mode 100644 index 0000000..e313482 --- /dev/null +++ b/bocloud.ams.service/.gitignore @@ -0,0 +1,10 @@ +*/target/* +*/.settings/* +*.classpath +*.project +*.prefs +*.class +*.iml +/.idea/* +*/.svn/* +/target/ diff --git a/bocloud.ams.service/pom.xml b/bocloud.ams.service/pom.xml new file mode 100644 index 0000000..fc1dc78 --- /dev/null +++ b/bocloud.ams.service/pom.xml @@ -0,0 +1,58 @@ + + + + com.bocloud + bocloud.ams + 6.5.0-LTS-SZ + + 4.0.0 + bocloud.ams.service + + + com.bocloud + bocloud.ams.task + + + com.bocloud + bocloud.ams.repository + + + com.bocloud + bocloud.boot.common + + + org.apache.velocity + velocity + 1.7 + + + org.freemarker + freemarker + + + org.apache.poi + poi + + + org.apache.poi + poi-ooxml + + + commons-fileupload + commons-fileupload + + + com.alibaba + easyexcel + 3.1.0 + + + poi-ooxml-schemas + org.apache.poi + + + + + \ No newline at end of file diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleItemService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleItemService.java new file mode 100644 index 0000000..7ebc929 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleItemService.java @@ -0,0 +1,13 @@ +package com.bocloud.ams.service.association; + +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.megatron.common.model.GeneralResult; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 18:02 + * @Description: + */ +public interface AutoRelationRuleItemService { + GeneralResult detail(Long id); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleService.java new file mode 100644 index 0000000..775a12e --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/AutoRelationRuleService.java @@ -0,0 +1,30 @@ +package com.bocloud.ams.service.association; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import java.util.List; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 16:47 + * @Description: + */ +public interface AutoRelationRuleService { + GeneralResult> list(Pager pager); + + GeneralResult save(AutoRelationRule rule, Long target); + + GeneralResult modify(Long id, AutoRelationRule rule, Long target); + + GeneralResult detail(Long id); + + GeneralResult remove(Long id, Long target); + + GeneralResult itemDetail(Long itemId); + + GeneralResult> list(Long moduleId, Long relationCategoryId); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleItemServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleItemServiceImpl.java new file mode 100644 index 0000000..1cd92e9 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleItemServiceImpl.java @@ -0,0 +1,39 @@ +package com.bocloud.ams.service.association.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.repository.association.AutoRelationRuleItemRepository; +import com.bocloud.ams.service.association.AutoRelationRuleItemService; +import com.megatron.common.model.GeneralResult; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 18:03 + * @Description: + */ +@Slf4j +@Service("autoRelationRuleItemService") +public class AutoRelationRuleItemServiceImpl implements AutoRelationRuleItemService { + + @Autowired + private AutoRelationRuleItemRepository autoRelationRuleItemRepository; + + @Override + public GeneralResult detail(Long id) { + try { + AutoRelationRuleItem item = autoRelationRuleItemRepository.query(id); + if (null == item) { + return new GeneralResult<>(false, "数据不存在"); + } + return new GeneralResult<>(true, item, "查询成功"); + } catch (Exception e) { + log.error("query rule item detail is fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleServiceImpl.java new file mode 100644 index 0000000..c7cad3f --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/association/impl/AutoRelationRuleServiceImpl.java @@ -0,0 +1,234 @@ +package com.bocloud.ams.service.association.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.bocloud.ams.repository.association.AutoRelationRuleItemRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleItemValueRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleRepository; +import com.bocloud.ams.service.association.AutoRelationRuleService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Author liuyuanyuan + * @Date 2022/5/9 0009 16:48 + * @Description: + */ +@Slf4j +@Service("autoRelationRuleService") +public class AutoRelationRuleServiceImpl implements AutoRelationRuleService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private AutoRelationRuleRepository autoRelationRuleRepository; + @Autowired + private AutoRelationRuleItemRepository autoRelationRuleItemRepository; + @Autowired + private AutoRelationRuleItemValueRepository autoRelationRuleItemValueRepository; + @Autowired + private RedisTemplate redisTemplate; + + @Override + public GeneralResult> list(Pager pager) { + GridBean gridBean; + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.autoRelationRuleRepository.count(pager.getParams()); + if (pager.getSimple()) { + List beans = this.autoRelationRuleRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.autoRelationRuleRepository.list(pager); + for (AutoRelationRule rule : list) { + rule.setCreator(redisTemplate.opsForValue().get("User_Name_" + rule.getCreatorId())); + List items = autoRelationRuleItemRepository.queryByRuleId(rule.getId()); + for (AutoRelationRuleItem item : items) { + List values = + autoRelationRuleItemValueRepository.queryByItemId(item.getId()); + item.setValues(values); + } + rule.setItems(items); + } + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query notice rule list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult save(AutoRelationRule rule, Long target) { + try { + if (autoRelationRuleRepository.countSameName(rule.getName()) > 0) { + return new GeneralResult<>(false, "添加失败,该名称已存在,请尝试其他名称"); + } + if (autoRelationRuleRepository.isOnly(rule.getRelationCategoryId(), rule.getSourceModuleId(), + rule.getTargetModuleId()) > 0) { + return new GeneralResult<>(false, "同一拓扑下,两个模型之间只允许存在一种关联规则,请检查"); + } + rule.setCreatorId(target); + rule.setGmtCreate(new Date()); + autoRelationRuleRepository.save(rule); + rule.getItems().forEach(item -> { + item.setRelationRuleId(rule.getId()); + item.setCreatorId(target); + item.setGmtCreate(new Date()); + autoRelationRuleItemRepository.save(item); + List itemValues = item.getValues(); + if (null != itemValues) { + itemValues.forEach(value -> { + value.setRelationRuleId(rule.getId()); + value.setItemId(item.getId()); + value.setCreatorId(target); + value.setGmtCreate(new Date()); + autoRelationRuleItemValueRepository.save(value); + }); + } + }); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("create rule is fail:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult modify(Long id, AutoRelationRule rule, Long target) { + String path = AutoRelationRule.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + AutoRelationRule relationRule = autoRelationRuleRepository.query(id); + if (null == relationRule) { + return new GeneralResult<>(false, "数据不存在"); + } + rule.setGmtModify(new Date()); + rule.setMenderId(target); + autoRelationRuleRepository.update(rule); + // 更新规则明细数据 + autoRelationRuleItemRepository.deleteByRuleId(id, target); + autoRelationRuleItemValueRepository.deleteByRuleId(id, target); + rule.getItems().forEach(item -> { + item.setId(null); + item.setRelationRuleId(rule.getId()); + item.setCreatorId(target); + item.setGmtCreate(new Date()); + autoRelationRuleItemRepository.save(item); + List itemValues = item.getValues(); + if (null != itemValues) { + itemValues.forEach(value -> { + value.setId(null); + value.setRelationRuleId(rule.getId()); + value.setItemId(item.getId()); + value.setCreatorId(target); + value.setGmtCreate(new Date()); + autoRelationRuleItemValueRepository.save(value); + }); + } + }); + return new GeneralResult<>(true, "更新成功"); + } catch (Exception e) { + log.error("modify rule is fail:", e); + return new GeneralResult<>(false, "更新失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + AutoRelationRule relationRule = autoRelationRuleRepository.query(id); + if (null == relationRule) { + return new GeneralResult<>(false, "数据不存在"); + } + // 查询规则明细数据 + List items = autoRelationRuleItemRepository.queryByRuleId(id); + for (AutoRelationRuleItem item : items) { + List values = + autoRelationRuleItemValueRepository.queryByItemId(item.getId()); + item.setValues(values); + } + relationRule.setItems(items); + return new GeneralResult<>(true, relationRule, "查询成功"); + } catch (Exception e) { + log.error("query rule detail is fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult remove(Long id, Long target) { + String path = AutoRelationRule.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + AutoRelationRule relationRule = autoRelationRuleRepository.query(id); + if (null == relationRule) { + return new GeneralResult<>(false, "数据不存在"); + } + autoRelationRuleRepository.delete(id, target); + // 删除关联数据 + autoRelationRuleItemRepository.deleteByRuleId(id, target); + autoRelationRuleItemValueRepository.deleteByRuleId(id, target); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("delete rule is fail:", e); + return new GeneralResult<>(false, "删除失败"); + } + } + + @Override + public GeneralResult itemDetail(Long itemId) { + try { + AutoRelationRuleItem ruleItem = autoRelationRuleItemRepository.query(itemId); + if (null == ruleItem) { + return new GeneralResult<>(false, "规则明细数据不存在"); + } + List itemValues = autoRelationRuleItemValueRepository.queryByItemId(itemId); + ruleItem.setValues(itemValues); + return new GeneralResult<>(true, ruleItem, "查询成功"); + } catch (Exception e) { + log.error("query rule item is fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> list(Long moduleId, Long categoryId) { + try { + List list = autoRelationRuleRepository.queryByModuleIdAndCategoryId(moduleId, categoryId); + return new GeneralResult<>(true, list, "查询成功"); + } catch (Exception e) { + log.error("Query rule list by moduleId and relationCategoryId fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/OperationalAuditService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/OperationalAuditService.java new file mode 100644 index 0000000..76b0ff8 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/OperationalAuditService.java @@ -0,0 +1,41 @@ +package com.bocloud.ams.service.audit; + +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.audit.OperationalAuditBak; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import java.util.Map; + +/** + * @Author liuyuanyuan + * @Date 2022/5/23 0023 17:45 + * @Description: + */ +public interface OperationalAuditService { + + GeneralResult> list(Pager pager); + + GeneralResult deatil(Long id); + + /** + * + * @param type 操作类型 + * @param moduleName 模型name + * @param instanceName 实例name + * @param moduleCode 模型code + * @param id + * @param userId + * @param beforeMap + * @param afterMap + * @return + */ + OperationalAudit buildLog(OperationalAuditType type, String moduleName, String instanceName, String moduleCode, Long id, Long userId, + Map beforeMap, + Map afterMap); + + GeneralResult> bakList(Pager pager); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/impl/OperationalAuditServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/impl/OperationalAuditServiceImpl.java new file mode 100644 index 0000000..525313e --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/audit/impl/OperationalAuditServiceImpl.java @@ -0,0 +1,196 @@ +package com.bocloud.ams.service.audit.impl; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.TableLog; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.audit.OperationalAuditBak; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.repository.TableLogRepository; +import com.bocloud.ams.repository.audit.OperationalAuditBakRepository; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.megatron.common.model.*; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.DateTools; +import com.megatron.common.utils.GridHelper; +import com.megatron.common.utils.ListTool; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author liuyuanyuan + * @Date 2022/5/23 0023 17:46 + * @Description: + */ +@Slf4j +@Service("operationalAuditService") +public class OperationalAuditServiceImpl implements OperationalAuditService { + + @Autowired + private OperationalAuditRepository operationalAuditRepository; + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private OperationalAuditBakRepository operationalAuditBakRepository; + @Autowired + private TableLogRepository tableLogRepository; + + @Override + public GeneralResult> list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + List params = pager.getParams(); + int total = operationalAuditRepository.count(params); + List audits = operationalAuditRepository.list(pager); + for (OperationalAudit audit : audits) { + audit.setOperator(redisTemplate.opsForValue().get("User_Name_" + audit.getCreatorId())); + } + GridBean bean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, audits); + return new GeneralResult>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("query cmdb operational audit list fail", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult deatil(Long id) { + try { + OperationalAudit audit = operationalAuditRepository.query(id); + if (null == audit) { + return new GeneralResult<>(false, "记录不存在"); + } + audit.setOperator(redisTemplate.opsForValue().get("User_Name_" + audit.getCreatorId())); + return new GeneralResult<>(true, audit, "查询成功"); + } catch (Exception e) { + log.error("query cmdb operational audit deatil fail", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 格式化实例中的日期和时间 + * + * @param instanceMap + */ + private void formatDate(Map instanceMap) { + instanceMap.forEach((key, value) -> { + if (value instanceof Date) { + instanceMap.put(key, DateTools.formatTime2String((Date) value, "yyyy-MM-dd")); + } + if (value instanceof Timestamp) { + instanceMap.put(key, DateTools.timestamp2DateTime(((Timestamp) value).getTime())); + } + if ((key.equals("gmtCreate") || key.equals("gmtModify")) && (value instanceof Long)) { + Instant instant = Instant.ofEpochMilli(Long.valueOf(value.toString())); + LocalDateTime time = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + formatter.format(time); + instanceMap.put(key, time); + } + }); + if (null != instanceMap.get("creatorId")) { + Long creatorId = Long.valueOf(instanceMap.get("creatorId").toString()); + instanceMap.put("creatorId", redisTemplate.opsForValue().get("User_Name_" + creatorId)); + } + if (null != instanceMap.get("menderId")) { + Long menderId = Long.valueOf(instanceMap.get("menderId").toString()); + instanceMap.put("menderId", redisTemplate.opsForValue().get("User_Name_" + menderId)); + } + } + + @Override + public OperationalAudit buildLog(OperationalAuditType type, String moduleName, String instanceName, + String moduleCode, Long id, Long userId, Map beforeMap, Map afterMap) { + try { + OperationalAudit audit = new OperationalAudit(); + audit.setTypeCode(type.getType()); + audit.setType(type.getTypeDesc()); + audit.setName(String.format("%s-%s", moduleName, instanceName)); + audit.setModuleCode(moduleCode); + audit.setInstanceId(id); + if (beforeMap != null) { + formatDate(beforeMap); + audit.setOaBefore(JSONObject.toJSONString(beforeMap)); + } + if (afterMap != null) { + formatDate(afterMap); + audit.setOaAfter(JSONObject.toJSONString(afterMap)); + } + audit.setCreatorId(userId); + audit.setOperator(redisTemplate.opsForValue().get("User_" + userId)); + return audit; + } catch (Exception e) { + log.error("审计操作记录保存失败:", e); + return null; + } + } + + @Override + public GeneralResult> bakList(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.getSorter().put(Common.ID, Common.ONE); + String startTime = null; + String endTime = null; + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("gmtCreate")) { + String time = paramMap.get("gmtCreate").toString(); + if (Sign.GET.name().equals(param.getSign().name())) { + startTime = time; + } else if (Sign.LET.name().equals(param.getSign().name())) { + endTime = time; + } + } + } + if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) { + return new GeneralResult<>(false, "日期必传!"); + } + List list = new ArrayList<>(); + //根据模板表查询出所有日志表 然后 使用并行流查询包含参数日期的库表 + List tableLogs = tableLogRepository.query(CmdbUtils.CMDB_OPERATIONAL_AUDIT_BAK); + String finalTimeGet = startTime; + String finalTimeLet = endTime; + //获取到数据中包含所查询的日期的历史备份表 + List tableList = tableLogs.parallelStream().map(item -> item.getName()).filter(item -> { + int count = 0; + try { + count = operationalAuditBakRepository.queryCount(item, finalTimeGet, finalTimeLet); + } catch (Exception e) { + log.error("查询操作审计备份表数量异常",e); + } + return count > 0; + }).collect(Collectors.toList()); + int total = 0; + if(CollectionUtils.isNotEmpty(tableList)){ + total = operationalAuditBakRepository.count(pager.getParams(), tableList); + list = operationalAuditBakRepository.list(pager, tableList); + for (OperationalAuditBak audit : list) { + audit.setOperator(redisTemplate.opsForValue().get("User_Name_" + audit.getCreatorId())); + } + } + GridBean bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询备份数据记录成功"); + } catch (Exception e) { + log.error("List task record fail:", e); + return new GeneralResult<>(false, "查询备份数据记录失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryItemService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryItemService.java new file mode 100644 index 0000000..a5ea9d8 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryItemService.java @@ -0,0 +1,21 @@ +package com.bocloud.ams.service.collection; + +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + + +/** + * @ClassName: CollectionHistoryItemService + * @Description + * @Author yangzhenrong + * @Date 2022/6/20 9:51 + * @Version 1.0 + **/ +public interface CollectionHistoryItemService { + + GeneralResult> list(Pager pager); + + GeneralResult> backupHistoryItems(Pager pager); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryService.java new file mode 100644 index 0000000..622d5dd --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionHistoryService.java @@ -0,0 +1,39 @@ +package com.bocloud.ams.service.collection; + +import com.bocloud.ams.entity.collection.CollectionHistory; +import com.bocloud.ams.entity.model.CollectionHistoryModel; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import java.util.List; +import java.util.Map; + +/** + * @ClassName: CollectionHistoryService + * @Description + * @Author yangzhenrong + * @Date 2022/6/15 20:30 + * @Version 1.0 + **/ +public interface CollectionHistoryService { + + GeneralResult>> instances(Pager pager, Long userId); + + GeneralResult> list(Pager pager); + + GeneralResult create(CollectionHistory history); + + GeneralResult modify(CollectionHistory history); + + GeneralResult> listByTaskInstanceId(Long taskInstanceId); + + GeneralResult detail(Long id); + + GeneralResult batchModify(CollectionHistoryModel historyModel, Long userId); + + GeneralResult> backupHistory(Pager pager); + + GeneralResult>> backupList(Pager pager, Long userId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskInstanceService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskInstanceService.java new file mode 100644 index 0000000..267af39 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskInstanceService.java @@ -0,0 +1,29 @@ +package com.bocloud.ams.service.collection; + +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.model.TaskInstanceBean; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 17:10 + * @Description: + */ +public interface CollectionTaskInstanceService { + + GeneralResult updateStatus(Long id, String status); + + GeneralResult modify(TaskInstanceBean bean, Long target); + + GeneralResult queryByTaskId(String taskId); + + GeneralResult> list(Pager pager); + + GeneralResult> bakList(Pager pager); + + GeneralResult detail(Long id); + + GeneralResult bakDetail(Long id,String name); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskService.java new file mode 100644 index 0000000..35407c3 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTaskService.java @@ -0,0 +1,61 @@ +package com.bocloud.ams.service.collection; + +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.model.OperateParam; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 17:10 + * @Description: + */ +public interface CollectionTaskService { + GeneralResult start(Long id, RequestContext context); + CollectionTaskInstance initInstance(CollectionTask task, RequestContext context); + + CollectionTask basic(Long id); + + GeneralResult isValid(String expression); + + GeneralResult> list(Pager pager); + + GeneralResult save(CollectionTask task, RequestContext context); + + GeneralResult modify(CollectionTask bean, RequestContext context); + + GeneralResult modifyType(Long id, RequestContext context); + + GeneralResult detail(Long id); + + GeneralResult remove(Long id, Long target); + + /** + * 判断是否存在高危命令 + * + * @param task + * @param userId + * @return + */ + GeneralResult checkCommand(CollectionTask task, Long userId); + + /** + * 高危命令处理 + * + * @param + * @param + * @return + */ +// public GeneralResult commandHandler(Long userId, String content); + + GeneralResult operate(OperateParam operateParam, Long id , Long target); + + GeneralResult removeScheduleIfLeader(Long id); + + GeneralResult addScheduleIfLeader(Long id ); + + void onApplicationReadyEvent(); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTemplateService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTemplateService.java new file mode 100644 index 0000000..4620bcf --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/CollectionTemplateService.java @@ -0,0 +1,28 @@ +package com.bocloud.ams.service.collection; + +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.bocloud.ams.entity.collection.CollectionTemplate; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 14:32 + * @Description: + */ +public interface CollectionTemplateService { + + GeneralResult> components(Pager pager); + + GeneralResult> list(Pager pager); + + GeneralResult save(CollectionTemplate template, Long target); + + GeneralResult modify(CollectionTemplate template, Long target); + + GeneralResult detail(Long id); + + GeneralResult remove(Long id, Long target); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryItemServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryItemServiceImpl.java new file mode 100644 index 0000000..8140c1d --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryItemServiceImpl.java @@ -0,0 +1,68 @@ +package com.bocloud.ams.service.collection.impl; + +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.bocloud.ams.repository.collection.CollectionHistoryItemRepository; +import com.bocloud.ams.service.collection.CollectionHistoryItemService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@Service("collectionHistoryItemService") +public class CollectionHistoryItemServiceImpl implements CollectionHistoryItemService { + @Autowired + private CollectionHistoryItemRepository historyItemRepository; + + @Override + public GeneralResult> list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.historyItemRepository.count(pager.getParams()); + List list = this.historyItemRepository.list(pager); + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Collection history item list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> backupHistoryItems(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + List params = pager.getParams(); + String tableName = null; + for (Param param : params) { + Map map = param.getParam(); + if(null != map && map.containsKey("tableName")){ + tableName = map.get("tableName").toString(); + map.remove("tableName"); + } + } + int total = this.historyItemRepository.count(tableName,pager.getParams()); + List list = this.historyItemRepository.list(tableName,pager); + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Collection history item list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryServiceImpl.java new file mode 100644 index 0000000..308bf41 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionHistoryServiceImpl.java @@ -0,0 +1,529 @@ +package com.bocloud.ams.service.collection.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionHistory; +import com.bocloud.ams.entity.collection.CollectionHistoryItem; +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.enums.CollectionEnum; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.CollectionHistoryModel; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.repository.collection.CollectionHistoryItemRepository; +import com.bocloud.ams.repository.collection.CollectionHistoryRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceRepository; +import com.bocloud.ams.repository.collection.CollectionTaskRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.collection.CollectionHistoryService; +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.bocloud.ams.service.instance.InstanceService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.google.common.collect.Maps; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.Sign; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.common.utils.JSONTools; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service("collectionHistoryService") +public class CollectionHistoryServiceImpl implements CollectionHistoryService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private CollectionHistoryRepository historyRepository; + @Autowired + private CollectionHistoryItemRepository historyItemRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private InstanceService instanceService; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private CollectionTaskInstanceRepository taskInstanceRepository; + @Autowired + private InstanceAutoRelationService instanceAutoRelationService; + @Autowired + private CollectionTaskRepository collectionTaskRepository; + @Autowired + private PropertyRepository propertyRepository; + + @Override + public GeneralResult>> instances(Pager pager, Long userId) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + List> list = new ArrayList<>(); + int total = 0; + // 模型 + Long moduleId = null; + String moduleCode = ""; + String historyType = null; + Long taskInstanceId = null; + // 实例属性条件查询 + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("moduleCode")) { + if (!StringUtils.isEmpty(paramMap.get("moduleCode").toString())) { + moduleCode = paramMap.get("moduleCode").toString(); + } + paramMap.remove("moduleCode"); + } + if (paramMap.containsKey("historyType")) { + if (!StringUtils.isEmpty(paramMap.get("historyType").toString())) { + historyType = paramMap.get("historyType").toString(); + } + paramMap.remove("historyType"); + } + if (paramMap.containsKey("taskInstanceId")) { + if (!StringUtils.isEmpty(paramMap.get("taskInstanceId").toString())) { + taskInstanceId = Long.valueOf(paramMap.get("taskInstanceId").toString()); + } + paramMap.remove("taskInstanceId"); + } + if (paramMap.containsKey("moduleId")) { + if (!StringUtils.isEmpty(paramMap.get("moduleId").toString())) { + moduleId = Long.valueOf(paramMap.get("moduleId").toString()); + } + } + } + // 拼接查询条件 + if (null != historyType) { + List historyList = historyRepository.queryByIdAndType(taskInstanceId, historyType); + List historyIds = + historyList.stream().map(history -> history.getInstanceId()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(historyIds)) { + HashMap inMap = Maps.newHashMap(); + inMap.put("id", generate(historyIds)); + Param inParam = new Param(); + inParam.setParam(inMap); + inParam.setSign(Sign.IN); + pager.getParams().add(inParam); + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + total = instanceRepository.count(pager.getParams(), table, valueTable, userId, true); + list = this.instanceRepository.list(pager, table, valueTable, userId, true); + instanceService.convertInstanceValue(list, moduleId, userId, true); + } + } + GridBean> bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("instance and value list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private Object generate(List hostIds) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < hostIds.size(); i++) { + builder.append(hostIds.get(i)).append(","); + } + builder.append(" -1 "); + return builder.toString(); + } + + @Override + public GeneralResult> list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.historyRepository.count(pager.getParams()); + List list = this.historyRepository.list(pager); + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Collection history list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult create(CollectionHistory history) { + try { + this.historyRepository.save(history); + List historyItems = history.getHistoryItems(); + if (CollectionUtils.isNotEmpty(historyItems)) { + for (CollectionHistoryItem item : historyItems) { + item.setHistoryId(history.getId()); + historyItemRepository.save(item); + } + } + return new GeneralResult<>(true, "新增成功"); + } catch (Exception e) { + log.error("Collection history create error:", e); + return new GeneralResult<>(false, "新增失败"); + } + } + + @Override + public GeneralResult modify(CollectionHistory history) { + final String path = CollectionHistory.class.getSimpleName() + "_" + history.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionHistory temp = historyRepository.query(history.getId()); + if (null == temp) { + return new GeneralResult<>(false, "记录不存在"); + } + LocaleBeanUtils.copyProperties(temp, history); + historyRepository.update(temp); + return new GeneralResult<>(true, "修改成功"); + } catch (Exception e) { + log.error("Collection history modify error:", e); + return new GeneralResult<>(false, "修改失败"); + } + } + + @Override + public GeneralResult> listByTaskInstanceId(Long taskInstanceId) { + try { + List histories = historyRepository.listByTaskInstanceId(taskInstanceId); + for (CollectionHistory history : histories) { + List items = historyItemRepository.listByHistoryId(history.getId()); + history.setHistoryItems(items); + } + return new GeneralResult<>(true, histories, "查询成功"); + } catch (Exception e) { + log.error("Collection history list error:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + CollectionHistory history = historyRepository.query(id); + List items = historyItemRepository.listByHistoryId(id); + history.setHistoryItems(items); + return new GeneralResult<>(true, history, "查询成功"); + } catch (Exception e) { + log.error("Collection history detail error:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult batchModify(CollectionHistoryModel historyModel, Long userId) { + if (null == historyModel.getIds() || historyModel.getIds().isEmpty()) { + return new GeneralResult<>(true, "批量操作失败"); + } + Long taskInstanceId = null; + try { + for (Long id : historyModel.getIds()) { + String path = CollectionHistory.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionHistory bean = historyRepository.query(id); + if (null == bean) { + return new GeneralResult<>(false, "数据不存在"); + } + taskInstanceId = bean.getTaskInstanceId(); + List items = historyItemRepository.listByHistoryId(id); + // 取消则标记成功 + if (CollectionEnum.historyOperate.CANCEL.name().equalsIgnoreCase(historyModel.getAction())) { + bean.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + } else if (CollectionEnum.historyOperate.UPDATE.name().equalsIgnoreCase(historyModel.getAction()) + && CollectionEnum.historyStatus.RECONCILED.name().equalsIgnoreCase(bean.getStatus())) { + // 手工调和 + JSONObject instanceObject = new JSONObject(); + instanceObject.put("moduleId", bean.getModuleId()); + CiModule module = moduleRepository.query(bean.getModuleId()); + if (null != module) { + instanceObject.put("moduleCode", module.getCode()); + } + List properties = propertyRepository.listNotHiddenByCmdbModuleId(bean.getModuleId()); + Map propertyMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(properties)) { + for (Property property : properties) { + propertyMap.put(property.getCode(), property); + } + } + Map dataMap = new HashMap<>(); + for (CollectionHistoryItem item : items) { + if (propertyMap.containsKey(item.getPropertyCode())) { + Property property = propertyMap.get(item.getPropertyCode()); + if ((PropertyConstant.PropertyType.CHECKBOX.equals(property.getType()) + || PropertyConstant.PropertyType.MULTISELECT.equals(property.getType()) + || PropertyConstant.PropertyType.JSON.equals(property.getType()) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(property.getType()) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(property.getType())) + && StringUtils.isNotEmpty(item.getAfterValue())) { + GeneralResult result = JSONTools.isJSON(item.getAfterValue()); + if (result.isSuccess()) { + instanceObject.put(item.getPropertyCode(), + JSONObject.parseObject(item.getAfterValue())); + } else { + instanceObject.put(item.getPropertyCode(), + JSONArray.parseArray(item.getAfterValue())); + } + } else { + instanceObject.put(item.getPropertyCode(), item.getAfterValue()); + } + dataMap.put(item.getPropertyCode(), item.getAfterValue()); + } + } + GeneralResult result = new GeneralResult<>(false, ""); + if (CollectionEnum.historyType.ADD.name().equalsIgnoreCase(bean.getType())) { + // 如果名称为空则自动生产 + if (null == instanceObject.getString("name")) { + instanceObject.put("name", "AutomaticGeneration" + System.currentTimeMillis()); + } + result = instanceService.create(instanceObject, userId, false); + if (result.isSuccess()) { + Instance instance = (Instance)result.getData(); + bean.setInstanceId(instance.getId()); + bean.setInstanceUuid(instance.getUuid()); + bean.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + // 自动关联 + CollectionTaskInstance taskInstance = + taskInstanceRepository.query(bean.getTaskInstanceId()); + CollectionTask task = collectionTaskRepository.query(taskInstance.getTaskId()); + if (task.getAutoRelation()) { + try { + instanceAutoRelationService.instanceAutoRelation(instance, userId); + } catch (Exception e) { + log.error("采集任务中存在实例关系自动关联失败情况", e); + } + } + } else { + bean.setStatus(CollectionEnum.historyStatus.FAILED.name()); + bean.setReason(result.getMessage()); + } + } else if (CollectionEnum.historyType.EDIT.name().equalsIgnoreCase(bean.getType())) { + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + List instanceValues = + instanceValueRepository.listByInstanceId(bean.getInstanceId(), instanceValueTable); + for (InstanceValue instanceValue : instanceValues) { + if (!dataMap.containsKey(instanceValue.getPropertyCode())) { + instanceObject.put(instanceValue.getPropertyCode(), + instanceValue.getPropertyValue()); + } + } + instanceObject.put(Common.ID, bean.getInstanceId()); + instanceObject.put(Common.UUID, bean.getInstanceUuid()); + result = instanceService.modify(instanceObject, userId); + if (result.isSuccess()) { + bean.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + // 自动关联 + CollectionTaskInstance taskInstance = + taskInstanceRepository.query(bean.getTaskInstanceId()); + CollectionTask task = collectionTaskRepository.query(taskInstance.getTaskId()); + if (task.getAutoRelation()) { + try { + Instance instance = (Instance)result.getData(); + instanceAutoRelationService.instanceAutoRelation(instance, userId); + } catch (Exception e) { + log.error("采集任务中存在实例关系自动关联失败情况", e); + } + } + } else { + bean.setStatus(CollectionEnum.historyStatus.FAILED.name()); + bean.setReason(result.getMessage()); + } + } + } + historyRepository.update(bean); + if (checkInstanceHistory(bean.getTaskInstanceId(), false)) { + if (CollectionEnum.historyStatus.SUCCESS.name().equals(bean.getStatus()) + && checkInstanceHistory(bean.getTaskInstanceId(), true)) { + taskInstanceRepository.updateStatus(bean.getTaskInstanceId(), + CollectionEnum.Status.SUCCESS.name()); + } else if (CollectionEnum.historyStatus.FAILED.name().equals(bean.getStatus())) { + taskInstanceRepository.updateStatus(bean.getTaskInstanceId(), + CollectionEnum.Status.ERROR.name()); + } + } + } catch (Exception e) { + log.error("Collection history batch modify error:", e); + // 复查任务状态 + CollectionTaskInstance taskInstance = taskInstanceRepository.query(taskInstanceId); + return new GeneralResult<>(false, taskInstance.getStatus(), "批量修改失败"); + } + } + // 复查任务状态 + CollectionTaskInstance taskInstance = taskInstanceRepository.query(taskInstanceId); + return new GeneralResult<>(true, taskInstance.getStatus(), "修改成功"); + } catch (Exception e) { + log.error("Collection history batch modify error:", e); + try { + CollectionTaskInstance taskInstance = taskInstanceRepository.query(taskInstanceId); + return new GeneralResult<>(false, taskInstance.getStatus(), "批量修改失败"); + } catch (Exception ex) { + log.error("query task inatance is error:", e); + } + return new GeneralResult<>(false, "批量修改失败"); + } + } + + @Override + public GeneralResult> backupHistory(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + List params = pager.getParams(); + String tableName = null; + for (Param param : params) { + Map map = param.getParam(); + if(null != map && map.containsKey("tableName")){ + tableName = map.get("tableName").toString(); + map.remove("tableName"); + } + } + if(StringUtils.isEmpty(tableName)){ + return new GeneralResult<>(false, "备份表参数必传"); + } + int total = this.historyRepository.count(tableName,pager.getParams()); + List list = this.historyRepository.list(tableName,pager); + int i = tableName.lastIndexOf("_"); + String substring = tableName.substring(i+1); + for (CollectionHistory collectionHistory : list) { + collectionHistory.setTableName("ci_collection_history_item_bak_" + substring); + } + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Collection history list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult>> backupList(Pager pager, Long userId) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + List params = pager.getParams(); + String tableName = null; + for (Param param : params) { + Map map = param.getParam(); + if(null != map && map.containsKey("tableName")){ + tableName = map.get("tableName").toString(); + map.remove("tableName"); + } + } + if(StringUtils.isEmpty(tableName)){ + return new GeneralResult<>(false, "备份表参数必传"); + } + List> list = new ArrayList<>(); + int total = 0; + // 模型 + Long moduleId = null; + String moduleCode = ""; + String historyType = null; + Long taskInstanceId = null; + // 实例属性条件查询 + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("moduleCode")) { + if (!StringUtils.isEmpty(paramMap.get("moduleCode").toString())) { + moduleCode = paramMap.get("moduleCode").toString(); + } + paramMap.remove("moduleCode"); + } + if (paramMap.containsKey("historyType")) { + if (!StringUtils.isEmpty(paramMap.get("historyType").toString())) { + historyType = paramMap.get("historyType").toString(); + } + paramMap.remove("historyType"); + } + if (paramMap.containsKey("taskInstanceId")) { + if (!StringUtils.isEmpty(paramMap.get("taskInstanceId").toString())) { + taskInstanceId = Long.valueOf(paramMap.get("taskInstanceId").toString()); + } + paramMap.remove("taskInstanceId"); + } + if (paramMap.containsKey("moduleId")) { + if (!StringUtils.isEmpty(paramMap.get("moduleId").toString())) { + moduleId = Long.valueOf(paramMap.get("moduleId").toString()); + } + } + } + // 拼接查询条件 + if (null != historyType) { + List historyList = historyRepository.queryByIdAndType(tableName,taskInstanceId, historyType); + List historyIds = historyList.stream().map(history -> history.getInstanceId()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(historyIds)) { + HashMap inMap = Maps.newHashMap(); + inMap.put("id", generate(historyIds)); + Param inParam = new Param(); + inParam.setParam(inMap); + inParam.setSign(Sign.IN); + pager.getParams().add(inParam); + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + total = instanceRepository.count(pager.getParams(), table, valueTable, userId, true); + list = this.instanceRepository.list(pager, table, valueTable, userId, true); + int i = tableName.lastIndexOf("_"); + String substring = tableName.substring(i+1); + for (Map map : list) { + map.put("tableName","ci_collection_history_item_bak_"+substring); + } + instanceService.convertInstanceValue(list, moduleId, userId, true); + } + } + GridBean> bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("instance and value list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private boolean checkInstanceHistory(Long taskInstanceId, boolean needAllSuccess) { + try { + List histories = historyRepository.listByTaskInstanceId(taskInstanceId); + for (CollectionHistory history : histories) { + if (needAllSuccess) { + if (!CollectionEnum.historyStatus.SUCCESS.name().equals(history.getStatus())) { + return false; + } + } else { + if (CollectionEnum.historyStatus.RECONCILED.name().equals(history.getStatus())) { + return false; + } + } + } + return true; + } catch (Exception e) { + return false; + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskInstanceServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskInstanceServiceImpl.java new file mode 100644 index 0000000..c8a8236 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskInstanceServiceImpl.java @@ -0,0 +1,351 @@ +package com.bocloud.ams.service.collection.impl; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.TableLog; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.model.TaskInstanceBean; +import com.bocloud.ams.repository.TableLogRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceRepository; +import com.bocloud.ams.service.collection.CollectionTaskInstanceService; +import com.bocloud.ams.task.model.HostResult; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.Sign; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @Author liuyuanyuan + * @Date 2022/6/13 0013 20:55 + * @Description: + */ +@Slf4j +@Service("collectionTaskInstanceService") +public class CollectionTaskInstanceServiceImpl implements CollectionTaskInstanceService { + @Autowired + private LockFactory lockFactory; + @Autowired + private CollectionTaskInstanceRepository collectionTaskInstanceRepository; + @Autowired + private TableLogRepository tableLogRepository; + @Autowired + private StringRedisTemplate redisTemplate; + + @Override + public GeneralResult updateStatus(Long id, String status) { + String path = CollectionTaskInstance.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTaskInstance temp = collectionTaskInstanceRepository.query(id); + if (null == temp) { + return new GeneralResult<>(false, "任务实例不存在"); + } + collectionTaskInstanceRepository.updateStatus(id, status); + return new GeneralResult<>(true, "修改成功"); + } catch (Exception e) { + log.error("Task instance modify fail:", e); + return new GeneralResult<>(false, "修改失败"); + } + } + + public static String[] getNullProperties (TaskInstanceBean bean) { + final BeanWrapper src = new BeanWrapperImpl(bean); + java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); + + Set emptyNames = new HashSet<>(); + for(java.beans.PropertyDescriptor pd : pds) { + Object srcValue = src.getPropertyValue(pd.getName()); + if (srcValue == null) emptyNames.add(pd.getName()); + } + String[] result = new String[emptyNames.size()]; + return emptyNames.toArray(result); + } + + @Override + public GeneralResult modify(TaskInstanceBean bean, Long target) { + String path = CollectionTaskInstance.class.getSimpleName() + "_" + bean.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTaskInstance temp = collectionTaskInstanceRepository.query(bean.getId()); + if (null == temp) { + return new GeneralResult<>(false, "任务实例不存在"); + } + BeanUtils.copyProperties(bean, temp, getNullProperties(bean)); + temp.setGmtModify(new Date()); + temp.setMenderId(target); + collectionTaskInstanceRepository.update(temp); + return new GeneralResult<>(true, "修改成功"); + } catch (Exception e) { + log.error("Task instance modify fail:", e); + return new GeneralResult<>(false, "修改失败"); + } + } + + @Override + public GeneralResult queryByTaskId(String taskId) { + try { + CollectionTaskInstance instance = collectionTaskInstanceRepository.queryByTaskId(taskId); + return new GeneralResult<>(true, instance, "查询成功"); + } catch (Exception e) { + log.error("query instance is fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> list(Pager pager) { + GridBean gridBean; + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.collectionTaskInstanceRepository.count(pager.getParams()); + if (pager.getSimple()) { + List beans = + this.collectionTaskInstanceRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.collectionTaskInstanceRepository.list(pager.getPage(), + pager.getRows(), pager.getParams(), pager.getSorter()); + list.forEach(instance -> instance + .setCreator(redisTemplate.opsForValue().get("User_Name_" + instance.getCreatorId()))); + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query Collection Task instance list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> bakList(Pager pager) { + GridBean gridBean; + try { + long start = System.currentTimeMillis(); + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + String startTime = null; + String endTime = null; + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("gmtCreate")) { + String time = paramMap.get("gmtCreate").toString(); + if (Sign.GET.name().equals(param.getSign().name())) { + startTime = time; + } else if (Sign.LET.name().equals(param.getSign().name())) { + endTime = time; + } + } + } + if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) { + return new GeneralResult<>(false, "日期必传!"); + } + int total = 0; + //根据模板表查询出所有日志表 然后 使用并行流查询包含参数日期的库表 + List tableLogs = tableLogRepository.query("ci_collection_task_instance_bak"); + List tableNames = tableLogs.stream().map(TableLog::getName).collect(Collectors.toList()); + String finalTimeGet = startTime; + String finalTimeLet = endTime; + //获取到数据中包含所查询的日期的历史备份表 + //long start1 = System.currentTimeMillis(); + List tableList = tableNames.parallelStream().filter(item -> { + List query = new ArrayList<>(); + try { + query = collectionTaskInstanceRepository.query(item, finalTimeGet, finalTimeLet); + } catch (Exception e) { + e.printStackTrace(); + } + return !ListTool.isEmpty(query); + }).collect(Collectors.toList()); + //long end1 = System.currentTimeMillis(); + //log.info("耗时1>>>>>>::::"+(end1-start1)); + //并行流计算count + //long start2 = System.currentTimeMillis(); + List totals = tableList.parallelStream().map(item -> { + try { + return collectionTaskInstanceRepository.count(pager.getParams(), item); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + }).collect(Collectors.toList()); + //long end2 = System.currentTimeMillis(); + //log.info("耗时2>>>>>>::::"+(end2-start2)); + total = totals.stream().collect(Collectors.summingInt(Integer::valueOf)); + //先计算出需要id集合 + //long start3 = System.currentTimeMillis(); + List collectionTaskInstances = tableList.stream().map(item -> + CompletableFuture.supplyAsync(() -> { + try { + return this.collectionTaskInstanceRepository.listIdBak(pager.getParams(), pager.getSorter(), item); + } catch (Exception e) { + e.printStackTrace(); + } + return new ArrayList(); + }) + ) + .collect(Collectors.toList()) + .stream() + .map(item -> item.join()) + .flatMap(item -> item.stream()) + .sorted((o1, o2) -> o2.getId().compareTo(o1.getId())) + .skip((pager.getPage() - 1) * pager.getRows()) + .limit(pager.getRows()) + .collect(Collectors.toList()); + //long end3 = System.currentTimeMillis(); + //log.info("耗时3>>>>>>::::"+(end3-start3)); + Map> collectMaps = collectionTaskInstances.stream().collect(Collectors.groupingBy(CollectionTaskInstance::getTableName)); + Set keySet = collectMaps.keySet(); + List keyList = new ArrayList<>(keySet); + //long start4 = System.currentTimeMillis(); + //根据id集合获取最终数据 + List collectionTaskInstanceList = keyList.stream().map(item -> + CompletableFuture.supplyAsync(() -> { + try { + String ids = collectMaps.get(item).stream().map(m -> m.getId().toString()).collect(Collectors.joining(",")); + Pager pg = new Pager(null, null, new ArrayList(), null); + pg.getParams().add(new Param(MapTools.simpleMap("id", ids), Sign.IN)); + return this.collectionTaskInstanceRepository.list(pg, item); + } catch (Exception e) { + e.printStackTrace(); + } + return new ArrayList(); + }) + ) + .collect(Collectors.toList()) + .stream() + .map(item -> item.join()) + .flatMap(item -> item.stream()) + .sorted((o1, o2) -> o2.getId().compareTo(o1.getId())) + .collect(Collectors.toList()); + //long end4 = System.currentTimeMillis(); + //log.info("耗时4>>>>>>::::"+(end4-start4)); + collectionTaskInstanceList.forEach(instance -> instance.setCreator(redisTemplate.opsForValue().get("User_Name_" + instance.getCreatorId()))); + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, collectionTaskInstanceList); + long end = System.currentTimeMillis(); + log.info("总耗时>>>>>>::::"+(end-start)); + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query Collection Task instance list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + CollectionTaskInstance instance = this.collectionTaskInstanceRepository.query(id); + Assert.notNull(instance, "数据不存在!"); + List successes = Lists.newArrayList(); + List failures = Lists.newArrayList(); + if (null != instance.getOutput()) { + GeneralResult result = JSONObject.parseObject(instance.getOutput(), GeneralResult.class); + if (!instance.getCode().contains("method") && !instance.getCode().contains("database")) { + if (null != result.getData()) { + List results = + JSONArray.parseArray(JSONObject.toJSONString(result.getData()), HostResult.class); + for (HostResult hostResult : results) { + // 查询主机名称 + if ("task.maintain.script".equalsIgnoreCase(instance.getCode())) { + List targets = JSONObject.parseObject(instance.getInput()) + .getJSONObject("target").getJSONArray("data").toJavaList(JSONObject.class); + Map hosts = Maps.newHashMap(); + for (JSONObject target : targets) { + hosts.put(target.getString("host"), target); + } + if (hosts.containsKey(hostResult.getHost())) { + hostResult.setRawName(hosts.get(hostResult.getHost()).getString("name")); + } + } + if (hostResult.isSuccess()) { + successes.add(hostResult); + } else { + failures.add(hostResult); + } + } + } + } + } + instance.setSuccesses(successes); + instance.setFailures(failures); + return new GeneralResult<>(true, instance, "查询任务详细成功"); + } catch (Exception e) { + log.error("Query task instance detail fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + + @Override + public GeneralResult bakDetail(Long id, String name) { + try { + CollectionTaskInstance instance = this.collectionTaskInstanceRepository.query(id, name); + Assert.notNull(instance, "数据不存在!"); + List successes = Lists.newArrayList(); + List failures = Lists.newArrayList(); + if (null != instance.getOutput()) { + GeneralResult result = JSONObject.parseObject(instance.getOutput(), GeneralResult.class); + if (!instance.getCode().contains("method") && !instance.getCode().contains("database")) { + if (null != result.getData()) { + List results = + JSONArray.parseArray(JSONObject.toJSONString(result.getData()), HostResult.class); + for (HostResult hostResult : results) { + // 查询主机名称 + if ("task.maintain.script".equalsIgnoreCase(instance.getCode())) { + List targets = JSONObject.parseObject(instance.getInput()) + .getJSONObject("target").getJSONArray("data").toJavaList(JSONObject.class); + Map hosts = Maps.newHashMap(); + for (JSONObject target : targets) { + hosts.put(target.getString("host"), target); + } + if (hosts.containsKey(hostResult.getHost())) { + hostResult.setRawName(hosts.get(hostResult.getHost()).getString("name")); + } + } + if (hostResult.isSuccess()) { + successes.add(hostResult); + } else { + failures.add(hostResult); + } + } + } + } + } + instance.setSuccesses(successes); + instance.setFailures(failures); + int i = name.lastIndexOf("_"); + String substring = name.substring(i + 1); + instance.setTableName("ci_collection_history_bak_" + substring); + return new GeneralResult<>(true, instance, "查询任务详细成功"); + } catch (Exception e) { + log.error("Query task instance detail fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskServiceImpl.java new file mode 100644 index 0000000..d78ba66 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTaskServiceImpl.java @@ -0,0 +1,776 @@ +package com.bocloud.ams.service.collection.impl; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.curator.framework.recipes.leader.LeaderLatchListener; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.Trigger; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronExpression; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.collection.CollectionTaskInstance; +import com.bocloud.ams.entity.collection.CollectionTemplate; +import com.bocloud.ams.entity.enums.ApplyStatus; +import com.bocloud.ams.entity.enums.CollectionEnum; +import com.bocloud.ams.entity.enums.Status; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.OperateParam; +import com.bocloud.ams.entity.model.TaskGraph; +import com.bocloud.ams.entity.model.TaskInstanceBean; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.repository.collection.CollectionComponentRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceRepository; +import com.bocloud.ams.repository.collection.CollectionTaskRepository; +import com.bocloud.ams.repository.collection.CollectionTemplateRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.collection.CollectionTaskInstanceService; +import com.bocloud.ams.service.collection.CollectionTaskService; +import com.bocloud.ams.service.internal.AmsInternalService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.bocloud.ams.task.executor.TaskJobSubmit; +import com.bocloud.ams.task.model.Job; +import com.bocloud.ams.task.model.enums.TaskParam; +import com.google.common.collect.Lists; +import com.megatron.common.encrypt.AESEncryptor; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.common.utils.IDFactory; +import com.megatron.framework.core.CurrentService; +import com.megatron.framework.http.core.HttpMethod; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Author liuyuanyuan + * @Date 2022/6/8 0008 17:12 + * @Description: + */ +@Slf4j +@Service("collectionTaskService") +public class CollectionTaskServiceImpl implements CollectionTaskService { + + private static final String FIXED = "fixed"; + private static final String SKIPED = "skiped"; + private static final Map> SCHEDULED_FUTURES = new ConcurrentHashMap<>(); + private ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + + @Autowired + private LockFactory lockFactory; + @Autowired + private CollectionTaskRepository collectionTaskRepository; + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private CollectionTemplateRepository collectionTemplateRepository; + @Autowired + private CollectionTaskInstanceRepository collectionTaskInstanceRepository; + @Autowired + private TaskJobSubmit taskJobSubmit; + @Autowired + private CollectionTaskInstanceService collectionTaskInstanceService; + @Autowired + private CurrentService currentService; + @Autowired + private AmsInternalService amsInternalService; + @Autowired + private CollectionComponentRepository collectionComponentRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private PropertyRepository propertyRepository; + + @Override + public GeneralResult> list(Pager pager) { + GridBean gridBean; + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.collectionTaskRepository.count(pager.getParams()); + if (pager.getSimple()) { + List beans = this.collectionTaskRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.collectionTaskRepository.list(pager.getPage(), pager.getRows(), + pager.getParams(), pager.getSorter()); + list.forEach( + task -> task.setCreator(redisTemplate.opsForValue().get("User_Name_" + task.getCreatorId()))); + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query Collection Task list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private int[] getRange(String field, int min, int max) { + int[] result = new int[2]; + if (!field.contains("-")) { + result[0] = result[1] = Integer.valueOf(field); + } else { + String[] split = org.springframework.util.StringUtils.delimitedListToStringArray(field, "-"); + if (split.length > 2) { + throw new IllegalArgumentException("Range has more than two fields: '" + field + "' in expression"); + } + result[0] = Integer.valueOf(split[0]); + result[1] = Integer.valueOf(split[1]); + } + if (result[0] >= max || result[1] >= max) { + throw new IllegalArgumentException("Range exceeds maximum (" + max + "): '" + field + "' in expression"); + } + if (result[0] < min || result[1] < min) { + throw new IllegalArgumentException("Range less than minimum (" + min + "): '" + field + "' in expression"); + } + if (result[0] > result[1]) { + throw new IllegalArgumentException("Invalid inverted range: '" + field + "' in expression"); + } + return result; + } + + private void buildGraph(CollectionTask task, CollectionTaskInstance instance) throws Exception { + JSONObject graph = new JSONObject(); + // 获取采集插件信息 + CollectionTemplate template = collectionTemplateRepository.query(task.getTemplateId()); + TaskGraph templateGraph = JSONObject.parseObject(String.valueOf(template.getGraph()), TaskGraph.class); + TaskGraph taskGraph = JSONObject.parseObject(String.valueOf(task.getGraph()), TaskGraph.class); + instance.setTimeout(templateGraph.getTimeout()); + JSONObject fronts = new JSONObject(); + if (templateGraph.getCollectionType().equalsIgnoreCase(CollectionEnum.collectionType.SCRIPT.getValue())) { + instance.setCode(CollectionEnum.workerCode.SCRIPT.getValue()); + fronts.put("content", templateGraph.getContent()); + fronts.put("category", templateGraph.getCategory()); + if (null != taskGraph.getParams()) { + fronts.put("params", JSONArray.parseArray(taskGraph.getParams())); + } + // 检查引用cmdb实例的目标参数 + JSONObject target = JSONObject.parseObject(taskGraph.getTarget()); + List components = collectionComponentRepository.queryByTemplateId(template.getId(), + CollectionEnum.parameter.INPUT_TARGET.getValue(), + CollectionEnum.parameterType.CMDB_INSTANCE.getValue()); + Boolean systemIsConfigure = false; + if (!components.isEmpty()) { + Map componentMap = components.stream() + .collect(Collectors.toMap(CollectionComponent::getPropertyId, Function.identity())); + // 查询实例数据 + String moduleCode = components.get(0).getModuleCode(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + List data = target.getJSONArray("data").toJavaList(JSONObject.class); + for (JSONObject targetData : data) { + List values = + instanceValueRepository.listByInstanceId(targetData.getLong("id"), valueTable); + Map valueMap = + values.stream().collect(Collectors.toMap(InstanceValue::getPropertyCode, Function.identity())); + for (Long propertyId : componentMap.keySet()) { + CollectionComponent component = componentMap.get(propertyId); + switch (component.getName()) { + case "AGENTS": + targetData.put("host", valueMap.get(component.getPropertyCode()).getPropertyValue()); + break; + case "PORT": + targetData.put("port", valueMap.get(component.getPropertyCode()).getPropertyValue()); + break; + case "USER": + targetData.put("user", valueMap.get(component.getPropertyCode()).getPropertyValue()); + break; + case "PASSWORD": + String pasd = valueMap.get(component.getPropertyCode()).getPropertyValue(); + // 处理未加密的密码 + if (CollectionEnum.parameterType.CMDB_INSTANCE.getValue() + .equalsIgnoreCase(component.getParameterType())) { + Property property = propertyRepository.query(component.getPropertyId()); + if (!PropertyConstant.PropertyType.TEXTENCRYPT + .equalsIgnoreCase(property.getType())) { + AESEncryptor aesEncryptor = new AESEncryptor(); + pasd = aesEncryptor.encrypt(pasd, null); + } + } + + targetData.put("pasd", pasd); + break; + case "SYSTEM": + String system = valueMap.get(component.getPropertyCode()).getPropertyValue(); + targetData.put("category", + system.toLowerCase().contains("windows") ? "windows" : "linux"); + systemIsConfigure = true; + break; + default: + break; + } + } + } + target.put("data", data); + } + if (!systemIsConfigure) { + List data = target.getJSONArray("data").toJavaList(JSONObject.class); + for (JSONObject targetData : data) { + String system = targetData.getString("category"); + targetData.put("category", system.toLowerCase().contains("windows") ? "windows" : "linux"); + } + target.put("data", data); + } + graph.put("target", target); + // 构建input + templateGraph.setParams(taskGraph.getParams()); + JSONObject input = new JSONObject(); + input.put("fronts", templateGraph); + input.put("target", target); + instance.setInput(input.toJSONString()); + } else if (templateGraph.getCollectionType() + .equalsIgnoreCase(CollectionEnum.collectionType.DATABASE.getValue())) { + instance.setCode(CollectionEnum.workerCode.DATABASE.getValue()); + fronts.put("content", templateGraph.getContent()); + fronts.put("jdbcUrl", templateGraph.getJdbcUrl()); + fronts.put("username", templateGraph.getUsername()); + fronts.put("category", templateGraph.getCategory()); + fronts.put("database", templateGraph.getDatabase()); + fronts.put("password", templateGraph.getPassword()); + // 构建input + JSONObject input = new JSONObject(); + input.put("fronts", JSONObject.parseObject(String.valueOf(template.getGraph()))); + instance.setInput(input.toJSONString()); + } else if (templateGraph.getCollectionType() + .equalsIgnoreCase(CollectionEnum.collectionType.METHOD.getValue())) { + instance.setCode(CollectionEnum.workerCode.METHOD.getValue()); + fronts.put("method", templateGraph.getMethod()); + fronts.put("format", templateGraph.getFormat()); + fronts.put("url", templateGraph.getUrl()); + fronts.put("params", JSONObject.parseObject(templateGraph.getParams())); + fronts.put("headers", JSONObject.parseObject(templateGraph.getHeaders())); + fronts.put("body", templateGraph.getBody()); + // 构建input + JSONObject input = new JSONObject(); + input.put("fronts", JSONObject.parseObject(String.valueOf(template.getGraph()))); + instance.setInput(input.toJSONString()); + } + graph.put("fronts", fronts); + graph.put("timeout", templateGraph.getTimeout()); + instance.setGraph(JSONObject.toJSONString(graph)); + } + + @Override + public GeneralResult start(Long id, RequestContext context) { + try { + CollectionTask task = this.basic(id); + if (null == task) { + return new GeneralResult<>(false, "任务不存在"); + } + CollectionTaskInstance instance = this.initInstance(task, context); + if (null == instance) { + return new GeneralResult<>(false, "执行失败:原因可能是作业参数格式错误"); + } + Job job = buildJob(instance); + boolean result = taskJobSubmit.subJob(job); + TaskInstanceBean instanceBean = new TaskInstanceBean(); + instanceBean.setId(instance.getId()); + if (result) { + instanceBean.setStatus(Status.Inst.RUNNING.name()); + instanceBean.setCollectionStatus(Status.Inst.RUNNING.name()); + collectionTaskInstanceService.modify(instanceBean, context.getTarget()); + return new GeneralResult<>(true, instance.getId(), "采集任务[" + instance.getName() + "]启动成功"); + } else { + instanceBean.setStatus(Status.Inst.FAILED.name()); + instanceBean.setCollectionStatus(Status.Inst.FAILED.name()); + collectionTaskInstanceService.modify(instanceBean, context.getTarget()); + return new GeneralResult<>(false, "启动失败"); + } + } catch (Exception e) { + log.info("启动失败", e); + return new GeneralResult<>(false, "启动失败"); + } + } + + private Job buildJob(CollectionTaskInstance task) { + Job job = new Job(); + job.setPriority(1); + job.setNeedFeedback(true); + job.setReplaceOnExist(true); + job.setParam(Common.NAME, task.getName()); + job.setParam(TaskParam.TASKTYPE.name(), "maintain"); + job.setParam(TaskParam.TASKDATA.name(), String.valueOf(task.getGraph())); + job.setParam(TaskParam.TASKCODE.name(), task.getCode()); + job.setParam(TaskParam.TIMEOUT.name(), String.valueOf(task.getTimeout())); + job.setMaxRetryTimes(0); + job.setTaskId(task.getUuid()); + return job; + } + + @Override + public CollectionTaskInstance initInstance(CollectionTask task, RequestContext context) { + try { + // 创建任务实例 + Long userId = context.getTarget(); + CollectionTaskInstance instance = new CollectionTaskInstance(userId, userId, userId, + task.getName() + System.currentTimeMillis(), Status.Inst.CREATED.name(), task.getRemark(), + task.getType(), task.getCron(), Status.Inst.CREATED.name()); + // 解析graph + buildGraph(task, instance); + instance.setUuid(IDFactory.instance().uuid()); + instance.setTaskId(task.getId()); + instance.setProps(JSONObject.toJSONString(context)); + instance.setGmtStart(new Date()); + this.collectionTaskInstanceRepository.save(instance); + return instance; + } catch (Exception e) { + log.error("initInstance [{}] exception !", task.getId(), e); + return null; + } + } + + @Override + public CollectionTask basic(Long id) { + try { + return this.collectionTaskRepository.query(id); + } catch (Exception e) { + log.error("Query task fail:", e); + return null; + } + } + + /** + * 校验cron表达式是否合法 + * + * @param expression + * @return + */ + @Override + public GeneralResult isValid(String expression) { + String message = "保存任务失败:Cron表达式有误或者执行时间是过去的时间"; + try { + String[] fields = org.springframework.util.StringUtils.tokenizeToStringArray(expression, " "); + List years = Lists.newArrayList(); + if (null == fields || fields.length < 6 || fields.length > 7) { + return new GeneralResult<>(false, message); + } else if (fields.length == 7) { + if (fields[6].contains("/")) { + return new GeneralResult<>(false, message); + } + String[] values = org.springframework.util.StringUtils.delimitedListToStringArray(fields[6], ","); + for (String value : values) { + int[] range = getRange(value, 0, 10000); + for (int i : range) { + years.add(i); + } + } + int currentYear = Calendar.getInstance().get(Calendar.YEAR); + boolean flag = false; + for (Integer year : years) { + if (year >= currentYear) { + flag = true; + } + } + if (!flag) { + return new GeneralResult<>(false, message); + } + expression = + fields[0] + " " + fields[1] + " " + fields[2] + " " + fields[3] + " " + fields[4] + " " + fields[5]; + } + CronExpression generator = CronExpression.parse(expression); + LocalDateTime time = generator.next(LocalDateTime.now()); + if (null == time) { + return new GeneralResult<>(false, message); + } + if (fields.length == 7) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(Date.from(time.atZone(ZoneId.systemDefault()).toInstant())); + int execYear = calendar.get(Calendar.YEAR); + for (Integer year : years) { + if (execYear > year) { + return new GeneralResult<>(false, message); + } + } + } + return new GeneralResult<>(true, "success"); + } catch (Exception e) { + log.warn("Cron expression is invalid"); + return new GeneralResult<>(false, message); + } + } + + private GeneralResult saveTask(CollectionTask task, Long userId, boolean isAdd) { + JSONObject graph = JSONObject.parseObject(JSONObject.toJSONString(task.getGraph())); + try { + if (StringUtils.isEmpty(task.getType())) { + task.setType("standard"); + } + // 校验cron表达式 + if (task.getType().equalsIgnoreCase(CollectionEnum.Task.SCHEDULED.getValue())) { + GeneralResult result = isValid(task.getCron()); + if (result.isFailed()) { + return result; + } + task.setStatus(ApplyStatus.CREATED.name()); + } + // 查询模板信息 + CollectionTemplate template = collectionTemplateRepository.query(task.getTemplateId()); + if (null == template) { + return new GeneralResult<>(false, "采集插件不存在"); + } + TaskGraph templateGraph = JSONObject.parseObject(String.valueOf(template.getGraph()), TaskGraph.class); + if (CollectionEnum.collectionType.SCRIPT.getValue().equalsIgnoreCase(templateGraph.getCollectionType())) { + JSONObject targets = graph.getJSONObject("target"); + List target = targets.getJSONArray("data").toJavaList(JSONObject.class); + boolean exists = false; + if (null != target && target.size() > 0) { + exists = true; + } + if (!exists) { + return new GeneralResult<>(false, "采集作业【" + task.getName() + "】没有关联目标主机"); + } + // // 密码加密 + // if (isAdd){ + // for (JSONObject object : target) { + // AESEncryptor AESEncryptor = new AESEncryptor(); + // object.put("pasd", AESEncryptor.encrypt(object.getString("pasd"), null)); + // } + // } + graph.put("target", targets); + } + // isAdd为true新增任务 + task.setGraph(JSONObject.toJSONString(graph)); + if (isAdd) { + task.setId(null); + task.setCreatorId(userId); + task.setUuid(IDFactory.instance().uuid()); + task.setGmtCreate(new Date()); + task.setStatus(ApplyStatus.DEVELOPING.name()); + this.collectionTaskRepository.save(task); + } else { + // 更新任务 + task.setGmtModify(new Date()); + task.setMenderId(userId); + this.collectionTaskRepository.update(task); + } + } catch (Exception e) { + log.error("Save task fail:", e); + return new GeneralResult<>(false, "保存任务失败"); + } + return new GeneralResult<>(true, task, "保存任务成功"); + } + + @Override + public GeneralResult save(CollectionTask task, RequestContext context) { + try { + // 判断是定时任务还是常规任务 + if (task.getType().equals(CollectionEnum.Task.STANDARD.getValue())) { + // 判断某种类的任务名称是否存在 + boolean flag = collectionTaskRepository.exists(task.getName(), task.getType()); + if (flag) { + return new GeneralResult<>(false, "该名称已存在,请重新输入!"); + } + // 检查任务中各节点是否正确 并入库 + GeneralResult result = saveTask(task, context.getTarget(), true); + if (result.isSuccess()) { + return new GeneralResult<>(true, result.getData(), "添加任务成功"); + } + return result; + } else { + CollectionTask queryEntity = collectionTaskRepository.query(task.getId()); + if (null == queryEntity) { + return GeneralResult.FAILED("数据不存在!"); + } + if (CollectionEnum.Task.SCHEDULED.getValue().equals(queryEntity.getType())) { + return GeneralResult.FAILED("此定时任务已存在!"); + } + if (StringUtils.isBlank(task.getCron())) { + return GeneralResult.FAILED("定时规则不能为空"); + } + if (isValid(task.getCron()).isFailed()) { + return GeneralResult.FAILED("定时规则错误"); + } + queryEntity.setType(CollectionEnum.Task.SCHEDULED.getValue()); + queryEntity.setStatus(CollectionEnum.Status.SUSPENDED.name()); + queryEntity.setCron(task.getCron()); + queryEntity.setMenderId(context.getTarget()); + collectionTaskRepository.update(queryEntity); + // 是否启动自动采集 + return new GeneralResult<>(true, queryEntity, "新增成功"); + } + } catch (Exception e) { + log.error("query task error:", e); + return new GeneralResult<>(false, "添加任务失败"); + } + } + + @Override + public GeneralResult modify(CollectionTask bean, RequestContext context) { + String path = CollectionTask.class.getSimpleName() + "_" + bean.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTask task = collectionTaskRepository.query(bean.getId()); + Assert.notNull(task, "数据不存在!"); + // 判断是定时任务还是常规任务 + if (bean.getType().equals(CollectionEnum.Task.STANDARD.getValue())) { + if (!task.getName().equals(bean.getName())) { + // 判断某种类的任务名称是否存在 + boolean flag = collectionTaskRepository.exists(bean.getName(), bean.getType()); + if (flag) { + return new GeneralResult<>(false, "该名称已存在,请重新输入!"); + } + } + if (task.getStatus().equals(Status.Inst.WAITTING.name())) { + return new GeneralResult<>(false, "修改失败:任务正在执行"); + } + BeanUtils.copyProperties(bean, task); + GeneralResult result = saveTask(task, context.getTarget(), false); + if (result.isSuccess()) { + return new GeneralResult<>(true, result.getData(), "修改任务成功"); + } else { + return result; + } + } else { + if (CollectionEnum.Status.RUNNING.name().equals(task.getStatus())) { + return GeneralResult.FAILED("该任务正在运行,请先暂停该任务"); + } + if (StringUtils.isBlank(bean.getCron())) { + return GeneralResult.FAILED("定时规则不能为空"); + } + if (isValid(bean.getCron()).isFailed()) { + return GeneralResult.FAILED("定时规则错误"); + } + task.setCron(bean.getCron()); + task.setMenderId(context.getTarget()); + collectionTaskRepository.update(task); + // 是否启动自动采集 + return new GeneralResult<>(true, task, "修改成功"); + } + } catch (Exception e) { + log.error("Update task fail:", e); + return new GeneralResult<>(false, "修改任务失败"); + } + } + + @Override + public GeneralResult modifyType(Long id, RequestContext context) { + String path = CollectionTask.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTask task = collectionTaskRepository.query(id); + if (null == task) { + return GeneralResult.FAILED("数据不存在!"); + } + // 判断是定时任务还是常规任务 + if (task.getType().equals(CollectionEnum.Task.STANDARD.getValue())) { + return new GeneralResult<>(false, "当前任务不是定时任务,任务修改失败!"); + } + if (!task.getStatus().equals(CollectionEnum.Status.SUSPENDED.name())) { + return GeneralResult.FAILED("当前任务状态为非暂停状态,任务修改失败!"); + } + task.setType(CollectionEnum.Task.STANDARD.getValue()); + task.setStatus(ApplyStatus.DEVELOPING.name()); + task.setCron(null); + task.setMenderId(context.getTarget()); + collectionTaskRepository.update(task); + // 是否启动自动采集 + return new GeneralResult<>(true, task, "任务修改成功!"); + } catch (Exception e) { + log.error("modify task error:", e); + return new GeneralResult<>(false, "任务修改失败!"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + CollectionTask task = this.collectionTaskRepository.query(id); + Assert.notNull(task, "数据不存在!"); + task.setCreator(redisTemplate.opsForValue().get("User_Name_" + task.getCreatorId())); + if (null != task.getMenderId()) { + task.setMender(redisTemplate.opsForValue().get("User_Name_" + task.getMenderId())); + } + return new GeneralResult<>(true, task, "查询任务详细成功"); + } catch (Exception e) { + log.error("Query task detail fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + + @Override + public GeneralResult checkCommand(CollectionTask task, Long userId) { + try { + // CollectionTemplate template = collectionTemplateRepository.query(task.getTemplateId()); + // if (template.getCollectionType().equalsIgnoreCase("script")) { + // GeneralResult result = commandHandler(userId, template.getGraph()); + // if (result.isFailed()) { + // return result; + // } + // } + return new GeneralResult<>(true, "不存在高危命令"); + } catch (Exception e) { + log.error("check Command is fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + + @Override + public GeneralResult operate(OperateParam operateParam, Long id, Long target) { + String path = CollectionTask.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTask task = collectionTaskRepository.query(id); + if (null == task) { + return new GeneralResult<>(false, "任务不存在"); + } + if ("run".equals(operateParam.getAction())) { + return this.run(id, target); + } else if ("stop".equals(operateParam.getAction())) { + return this.stop(id, target); + } + return new GeneralResult<>(false, "不支持的操作类型"); + } catch (Exception e) { + return GeneralResult.FAILED("修改失败"); + } + } + + private GeneralResult run(Long id, Long userId) { + boolean success = amsInternalService.scheduleInspectBroadcast(id, HttpMethod.GET); + if (success) { + collectionTaskRepository.changeStatus(id, CollectionEnum.Status.RUNNING.name(), userId); + } + return new GeneralResult<>(success, success ? "启动定时任务成功" : "启动定时任务失败"); + } + + private GeneralResult stop(Long id, Long userId) { + boolean success = amsInternalService.scheduleInspectBroadcast(id, HttpMethod.DELETE); + if (success) { + collectionTaskRepository.changeStatus(id, CollectionEnum.Status.SUSPENDED.name(), userId); + } + return new GeneralResult<>(success, success ? "停止定时任务成功" : "停止定时任务失败"); + } + + @Override + public GeneralResult removeScheduleIfLeader(Long id) { + if (!currentService.isLeader()) { + log.info("收到定时任务[id={}]删除定时任务请求,当前服务非主服务,已经忽略", id); + return new GeneralResult<>(true, SKIPED, "success"); + } + try { + CollectionTask timing = collectionTaskRepository.query(id); + Assert.notNull(timing, "定时任务数据不存在"); + this.removeSchedule(timing); + return new GeneralResult<>(true, FIXED, "success"); + } catch (Exception e) { + log.error("RemoveScheduleIfLeader fail:", e); + return new GeneralResult<>(false, "fail"); + } + } + + @Override + public GeneralResult addScheduleIfLeader(Long id) { + if (!currentService.isLeader()) { + log.info("收到定时任务[id={}]添加定时任务请求,当前服务非主服务,已经忽略", id); + return new GeneralResult<>(true, SKIPED, "success"); + } + try { + CollectionTask timing = collectionTaskRepository.query(id); + Assert.notNull(timing, "定时任务数据不存在"); + this.addSchedule(timing); + return new GeneralResult<>(true, FIXED, "success"); + } catch (Exception e) { + log.error("AddScheduleIfLeader fail:", e); + return new GeneralResult<>(false, "fail"); + } + } + + private void addSchedule(CollectionTask task) { + if (SCHEDULED_FUTURES.containsKey(task.getId())) { + this.removeSchedule(task); + } + Trigger trigger = new CronTrigger(task.getCron()); + ScheduledFuture future = taskScheduler.schedule(() -> { + RequestContext context = new RequestContext(); + context.setTarget(task.getMenderId()); + this.start(task.getId(), context); + }, trigger); + SCHEDULED_FUTURES.put(task.getId(), future); + log.info("定时任务[{}]已经添加到定时任务,调度策略:{}", task.getName(), task.getCron()); + log.info("定时任务:" + JSONObject.toJSONString(SCHEDULED_FUTURES.keySet())); + } + + private void removeSchedule(CollectionTask collectionTask) { + ScheduledFuture future = SCHEDULED_FUTURES.remove(collectionTask.getId()); + if (future != null) { + future.cancel(true); + } + log.info("定时任务[{}]已经从定时任务中移除", collectionTask.getName()); + } + + @Override + public void onApplicationReadyEvent() { + taskScheduler.setPoolSize(Runtime.getRuntime().availableProcessors()); + taskScheduler.setThreadNamePrefix("TimeInspect-"); + taskScheduler.initialize(); + CollectionTaskServiceImpl collectionTaskServiceImpl = this; + LeaderLatchListener listener = new LeaderLatchListener() { + @Override + public void isLeader() { + List tasks = collectionTaskRepository.findAllByRunning(Status.Inst.RUNNING.name()); + tasks.forEach(collectionTaskServiceImpl::addSchedule); + } + + @Override + public void notLeader() { + List tasks = collectionTaskRepository.findAllByRunning(Status.Inst.RUNNING.name()); + tasks.forEach(collectionTaskServiceImpl::removeSchedule); + } + }; + try { + currentService.addListener(listener); + } catch (Exception e) { + log.error("定时任务初始化失败:{}", e.getMessage()); + } + if (currentService.isLeader()) { + listener.isLeader(); + } + } + + @Override + public GeneralResult remove(Long id, Long target) { + String path = CollectionTask.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTask task = this.collectionTaskRepository.query(id); + Assert.notNull(task, "数据不存在!"); + Assert.isTrue(!task.getStatus().equals(Status.Inst.WAITTING.name()), "任务正在执行"); + Assert.isTrue(!task.getStatus().equals(Status.Inst.RUNNING.name()), "定时任务正在运行中,请先暂停"); + boolean result = this.collectionTaskRepository.delete(id, target); + return result ? new GeneralResult<>(true, "删除任务成功") : new GeneralResult<>(false, "删除任务失败"); + } catch (Exception e) { + log.error("Remove task fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTemplateServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTemplateServiceImpl.java new file mode 100644 index 0000000..961e770 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/collection/impl/CollectionTemplateServiceImpl.java @@ -0,0 +1,255 @@ +package com.bocloud.ams.service.collection.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.collection.CollectionTemplate; +import com.bocloud.ams.entity.enums.CollectionEnum; +import com.bocloud.ams.entity.model.TaskGraph; +import com.bocloud.ams.repository.collection.CollectionComponentRepository; +import com.bocloud.ams.repository.collection.CollectionTaskRepository; +import com.bocloud.ams.repository.collection.CollectionTemplateRepository; +import com.bocloud.ams.service.collection.CollectionTemplateService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Author liuyuanyuan + * @Date 2022/6/7 0007 14:32 + * @Description: + */ +@Slf4j +@Service("collectionTemplateService") +public class CollectionTemplateServiceImpl implements CollectionTemplateService { + @Autowired + private LockFactory lockFactory; + @Autowired + private CollectionTemplateRepository collectionTemplateRepository; + @Autowired + private CollectionComponentRepository collectionComponentRepository; + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private CollectionTaskRepository collectionTaskRepository; + + @Override + public GeneralResult> components(Pager pager) { + GridBean gridBean; + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.collectionComponentRepository.count(pager.getParams()); + if (pager.getSimple()) { + List beans = this.collectionComponentRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.collectionComponentRepository.list(pager.getPage(), + pager.getRows(), pager.getParams(), pager.getSorter()); + list.forEach(template -> template + .setCreator(redisTemplate.opsForValue().get("User_Name_" + template.getCreatorId()))); + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query Collection Component list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> list(Pager pager) { + GridBean gridBean; + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.collectionTemplateRepository.count(pager.getParams()); + if (pager.getSimple()) { + List beans = this.collectionTemplateRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.collectionTemplateRepository.list(pager.getPage(), pager.getRows(), + pager.getParams(), pager.getSorter()); + list.forEach(template -> { + template.setCreator(redisTemplate.opsForValue().get("User_Name_" + template.getCreatorId())); + List components = null; + try { + components = collectionComponentRepository.queryByTemplateId(template.getId()); + } catch (Exception e) { + log.error("Query Collection Components list fail:", e); + } + template.setComponents(components); + }); + gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Query Collection Template list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult save(CollectionTemplate template, Long target) { + try { + // 判断某种类的作业模板名称是否存在 + boolean flag = collectionTemplateRepository.exists(template.getName()); + if (flag) { + return new GeneralResult<>(false, "该插件名称已存在,无法添加"); + } + GeneralResult result = saveTask(template, true); + if (result.isFailed()) { + return result; + } + result = saveComponent(template, true, target); + if (result.isFailed()) { + return result; + } + return new GeneralResult<>(true, "添加采集模板成功"); + } catch (Exception e) { + log.error("save collection template error:", e); + return new GeneralResult<>(false, "添加采集模板失败"); + } + } + + private GeneralResult saveComponent(CollectionTemplate template, boolean isAdd, Long userId) { + try { + List collectionComponents = template.getComponents(); + List components = collectionComponents.stream().map(component -> { + component.setTemplateId(template.getId()); + component.setCreatorId(userId); + component.setGmtCreate(new Date()); + component.setId(null); + return component; + }).collect(Collectors.toList()); + if (!isAdd) { + collectionComponentRepository.deleteByTemplate(template.getId(), userId); + } + if (!collectionComponents.isEmpty()) { + collectionComponentRepository.batchSave(components, 100); + } + } catch (Exception e) { + log.error("Save collection components fail:", e); + return new GeneralResult<>(false, "保存采集模板组件失败"); + } + return new GeneralResult<>(true, template, "保存采集模板组件成功"); + } + + private GeneralResult saveTask(CollectionTemplate template, boolean isAdd) { + TaskGraph graph = JSONObject.parseObject(JSONObject.toJSONString(template.getGraph()), TaskGraph.class); + if (CollectionEnum.collectionType.SCRIPT.getValue().equalsIgnoreCase(graph.getCollectionType())) { + if (null == graph.getContent()) { + return new GeneralResult<>(false, "脚本内容为空"); + } + if (null == graph.getCategory()) { + return new GeneralResult<>(false, "脚本类型为空"); + } + } + try { + // isAdd为true新增作业模板 + template.setGraph(JSONObject.toJSONString(template.getGraph())); + if (isAdd) { + template.setGmtCreate(new Date()); + this.collectionTemplateRepository.save(template); + } else { + // 更新作业模板 + template.setGmtModify(new Date()); + this.collectionTemplateRepository.update(template); + } + } catch (Exception e) { + log.error("Save collection template fail:", e); + return new GeneralResult<>(false, "保存采集模板失败"); + } + return new GeneralResult<>(true, template, "保存采集模板成功"); + } + + @Override + public GeneralResult modify(CollectionTemplate template, Long target) { + String path = CollectionTemplate.class.getSimpleName() + "_" + template.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CollectionTemplate collectionTemplate = this.collectionTemplateRepository.query(template.getId()); + Assert.notNull(collectionTemplate, "数据不存在!"); + if (!collectionTemplate.getName().equals(template.getName())) { + // 判断某种类的作业模板名称是否存在 + boolean flag = collectionTemplateRepository.exists(template.getName()); + if (flag) { + return new GeneralResult<>(false, "该名称已存在,请重新输入!"); + } + } + collectionTemplate.setGraph(template.getGraph()); + collectionTemplate.setName(template.getName()); + collectionTemplate.setRemark(template.getRemark()); + collectionTemplate.setCollectionType(template.getCollectionType()); + GeneralResult result = saveTask(collectionTemplate, false); + if (result.isFailed()) { + return result; + } + result = saveComponent(template, false, target); + if (result.isFailed()) { + return result; + } + return new GeneralResult<>(true, "修改采集模板成功"); + } catch (Exception e) { + log.error("Update collection template fail:", e); + return new GeneralResult<>(false, "修改采集模板失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + CollectionTemplate template = collectionTemplateRepository.query(id); + template.setCreator(redisTemplate.opsForValue().get("User_Name_" + template.getCreatorId())); + Assert.notNull(template, "数据不存在!"); + List components = collectionComponentRepository.queryByTemplateId(id); + template.setComponents(components); + return new GeneralResult<>(true, template, "查询采集模板详细成功"); + } catch (Exception e) { + log.error("Query collection detail template fail:", e); + return new GeneralResult<>(false, e.getMessage()); + } + } + + @Override + public GeneralResult remove(Long id, Long target) { + String path = CollectionTemplate.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + // 判断当前插件是否有被引用 + List tasks = collectionTaskRepository.queryByTemplateId(id); + if (0 < tasks.size()) { + return new GeneralResult<>(false, "当前插件存在采集任务,不允许删除"); + } + collectionTemplateRepository.delete(id, target); + collectionComponentRepository.deleteByTemplate(id, target); + return new GeneralResult<>(true, "删除采集模板成功"); + } catch (Exception e) { + log.error("Remove collection template fail:", e); + return new GeneralResult<>(false, "删除采集模板失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/CmdbConfigService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/CmdbConfigService.java new file mode 100644 index 0000000..48115f3 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/CmdbConfigService.java @@ -0,0 +1,36 @@ +package com.bocloud.ams.service.config; + +import com.alibaba.fastjson.JSONArray; +import com.bocloud.ams.entity.config.CmdbConfig; +import com.megatron.common.exception.InternalServerException; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.Result; + +import java.util.List; +import java.util.Map; + +public interface CmdbConfigService { + + /** + * 更新配置 + * + * @param config + * @return + */ + Result modify(CmdbConfig config) throws InternalServerException; + + /** + * 批量修改 + * + * @param list + * @param context + * @return + */ + Result batchUpdate(List list, RequestContext context); + + GeneralResult> listConfigs(String category, List codes); + + GeneralResult listCategoryTree(String category); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/impl/CmdbConfigServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/impl/CmdbConfigServiceImpl.java new file mode 100644 index 0000000..4bae6d6 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/config/impl/CmdbConfigServiceImpl.java @@ -0,0 +1,150 @@ +package com.bocloud.ams.service.config.impl; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.config.CmdbConfig; +import com.bocloud.ams.repository.config.CmdbConfigRepository; +import com.bocloud.ams.service.config.CmdbConfigService; +import com.megatron.common.exception.InternalServerException; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.Result; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@Service("cmdbConfigService") +public class CmdbConfigServiceImpl implements CmdbConfigService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private CmdbConfigRepository cmdbConfigRepository; + @Autowired + private StringRedisTemplate redisTemplate; + + /** + * 修改系统配置 + * + * @param config + * 系统配置对象 + * @return + * @throws InternalServerException + */ + @Override + @Transactional(rollbackFor = InternalServerException.class) + public Result modify(CmdbConfig config) throws InternalServerException { + String path = CmdbConfig.class.getSimpleName() + "_" + config.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CmdbConfig object = this.cmdbConfigRepository.query(config.getId()); + Assert.notNull(object, "CmdbConfig does not exist!"); + BeanUtils.copyProperties(config, object); + object.setGmtModify(new Date()); + this.cmdbConfigRepository.modify(object); + redisTemplate.opsForValue().set(object.getCode(), object.getValue()); + return new Result(true, "修改成功"); + } catch (Exception e) { + log.error("Modify CmdbConfig fail:", e); + throw new InternalServerException("修改失败," + e.getMessage(), e, e.getMessage()); + } + } + + /** + * 批量更新系统配置 + * + * @param models + * 系统配置集合 + * @return + */ + @Override + public Result batchUpdate(List models, RequestContext context) { + String[] titles = new String[] {"id", "value", "gmtModify", "menderId"}; + try { + Map configMap = new HashMap<>(8); + for (CmdbConfig model : models) { + configMap.put(model.getCode(), model.getValue()); + } + Set configCodes = configMap.keySet(); + List list = cmdbConfigRepository.listByCodes(configCodes); + for (CmdbConfig config : list) { + config.setValue(configMap.get(config.getCode())); + config.setMenderId(context.getTarget()); + config.setGmtModify(new Date()); + } + boolean flag = cmdbConfigRepository.batchUpdate(list, titles); + if (!flag) { + return new GeneralResult<>(false, "修改失败"); + } + for (CmdbConfig config : list) { + redisTemplate.opsForValue().set(config.getCode(), config.getValue()); + } + return new GeneralResult<>(true, "修改成功"); + } catch (Exception e) { + log.error("batch modify system config fail:", e); + return new GeneralResult<>(false, "修改失败" + e.getMessage()); + } + } + + @Override + public GeneralResult> listConfigs(String category, List codes) { + try { + List configs; + if (StringUtils.hasText(category)) { + configs = cmdbConfigRepository.listByCategory(category); + } else { + configs = cmdbConfigRepository.listByCodes(new HashSet<>(codes)); + } + Map configMap = + configs.stream().collect(Collectors.toMap(CmdbConfig::getCode, Function.identity())); + Map result = new HashMap<>(8); + for (Map.Entry entry : configMap.entrySet()) { + String value = entry.getValue().getValue(); + result.put(entry.getKey(), value); + } + return new GeneralResult<>(true, result, "查询成功"); + } catch (Exception e) { + log.error("list configs by codes error,", e); + return new GeneralResult<>(false, "查询失败:" + e.getMessage()); + } + } + + @Override + public GeneralResult listCategoryTree(String category) { + try { + List configs = cmdbConfigRepository.listByCategory(category); + Map> configMap = + configs.stream().collect(Collectors.groupingBy(CmdbConfig::getSubclass)); + JSONArray jsonArray = new JSONArray(); + for (Map.Entry> entry : configMap.entrySet()) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", entry.getKey()); + jsonObject.put("values", entry.getValue()); + jsonArray.add(jsonObject); + } + return new GeneralResult<>(true, jsonArray, "查询成功"); + } catch (Exception e) { + log.error("list configs tree by category error,", e); + return new GeneralResult<>(false, "查询失败:" + e.getMessage()); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/core/CmdbConfigCache.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/core/CmdbConfigCache.java new file mode 100644 index 0000000..b422365 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/core/CmdbConfigCache.java @@ -0,0 +1,56 @@ +package com.bocloud.ams.service.core; + +import com.bocloud.ams.entity.config.CmdbConfig; +import com.bocloud.ams.repository.config.CmdbConfigRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.util.List; + +@Slf4j +@Component +public class CmdbConfigCache implements InitializingBean { + + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private CmdbConfigRepository cmdbConfigRepository; + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + + public void putConfigCache(String code, String value) { + this.redisTemplate.opsForValue().set(code, value); + } + + public String getConfigValue(String code) { + return redisTemplate.opsForValue().get(code); + } + + @Override + public void afterPropertiesSet() { + taskExecutor.execute(this::addConfigCache); + } + + public void addConfigCache() { + try { + List configs = cmdbConfigRepository.listAll(); + for (CmdbConfig config : configs) { + if (null == config.getValue()) { + continue; + } + if (!StringUtils.hasText(getConfigValue(config.getCode()))) { + putConfigCache(config.getCode(), config.getValue()); + } + } + } catch (Exception e) { + log.error("put cmdb config cache error,", e); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAuthorityService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAuthorityService.java new file mode 100644 index 0000000..e0b0377 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAuthorityService.java @@ -0,0 +1,31 @@ +package com.bocloud.ams.service.instance; + +import com.bocloud.ams.entity.instance.InstanceAuthority; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; + +import java.util.List; + +/** + * @ClassName: CmdbInstanceAuthorityService + * @Description + * @Author yangzhenrong + * @Date 2022/5/23 18:18 + * @Version 1.0 + **/ +public interface InstanceAuthorityService { + + + GeneralResult list(Pager pager); + + GeneralResult create(InstanceAuthority authority, Long userId); + + GeneralResult remove(Long id, Long userId); + + GeneralResult modify(InstanceAuthority authority, Long userId); + + GeneralResult removeByRole(InstanceAuthority authority, Long userId); + + GeneralResult listByInstanceId(Long moduleId, Long instanceId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAutoRelationService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAutoRelationService.java new file mode 100644 index 0000000..2ec00be --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceAutoRelationService.java @@ -0,0 +1,35 @@ +package com.bocloud.ams.service.instance; + +import com.bocloud.ams.entity.instance.Instance; +import com.megatron.common.model.GeneralResult; + +/** + * @Author majiali + * @Date 2022/5/16 0016 14:24 + * @Description: + */ +public interface InstanceAutoRelationService { + + /** + * @param instance 实例信息 + * @param userId 用户id + * @Description: 实例创建(实例变更) 属性变更,触发自动关联任务 + * @Author majiali + * @CreateTime 2022/6/6 9:11 + */ + GeneralResult instanceAutoRelation(Instance instance, Long userId); + + /** + * @Description: 全量处理模型实例关系 + * @Author majiali + * @CreateTime 2022/6/9 15:03 + */ + GeneralResult autoRelation(); + + /** + * @Description: 处理模型实例关系 + * @Author majiali + * @CreateTime 2022/6/14 15:03 + */ + GeneralResult autoRelationByModuleId(Long moduleId); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceHistoryService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceHistoryService.java new file mode 100644 index 0000000..9b796f9 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceHistoryService.java @@ -0,0 +1,23 @@ +package com.bocloud.ams.service.instance; + +import com.bocloud.ams.entity.instance.InstanceHistory; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; + +/** + * @ClassName: CmdbInstanceHistoryService + * @Description + * @Author yangzhenrong + * @Date 2022/5/16 17:07 + * @Version 1.0 + **/ +public interface InstanceHistoryService { + + + GeneralResult list(Pager pager); + + GeneralResult create(InstanceHistory history, Long userId); + + GeneralResult listByInstanceId(Long moduleId, Long instanceId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationHistoryRecordService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationHistoryRecordService.java new file mode 100644 index 0000000..33dd6dd --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationHistoryRecordService.java @@ -0,0 +1,54 @@ +package com.bocloud.ams.service.instance; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; + +import java.util.List; + +/** + * @Author majiali + * @Date 2022/6/8 15:49 + * @Version 1.0 + **/ +public interface InstanceRelationHistoryRecordService { + + /** + * 获取详情 + * + * @param id + * @return + */ + public GeneralResult detail(Long id) throws Exception; + + /** + * 列表分页查询 + * + * @param pager + * @return + */ + public GeneralResult list(Pager pager); + + public GeneralResult cancel(Long id, RequestContext context); + + public GeneralResult reconcile(Long id, RequestContext context); + + public GeneralResult preflight(Long id, RequestContext context); + + public GeneralResult batchCancel(List ids, RequestContext context); + + /** + * @param instanceRelation 实例关系 + * @param isSource 当前实例是否是源实例 + * @param status 状态 SUCCESS-成功 FAILED-失败 + * @param type 类型 CANCEL-取消关联 RELATION-关联 + * @param reason 失败原因 + * @param context + * @Description: 添加关联历史(手动关联) + * @Author majiali + * @CreateTime 2022/6/14 16:13 + */ + public GeneralResult save(InstanceRelation instanceRelation, boolean isSource, String status, String type, String reason, RequestContext context); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationService.java new file mode 100644 index 0000000..1e93e33 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceRelationService.java @@ -0,0 +1,21 @@ +package com.bocloud.ams.service.instance; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; + +/** + * @Author liuyuanyuan + * @Date 2022/5/16 0016 14:24 + * @Description: + */ +public interface InstanceRelationService { + + GeneralResult createTable(String relationCategoryCode, Long userId) throws Exception; + + GeneralResult dropTable(String relationCategoryCode, Long userId) throws Exception; + + GeneralResult create(InstanceRelation instanceRelation, RequestContext context); + + GeneralResult remove(Long id, String relationCategoryCode, Long currentModuleId, Long currentInstanceId, RequestContext context); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceService.java new file mode 100644 index 0000000..7cf0c0f --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceService.java @@ -0,0 +1,57 @@ +package com.bocloud.ams.service.instance; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.model.InstanceBean; +import com.bocloud.ams.entity.model.InstanceTopo; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * @ClassName: CmdbInstanceService + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 11:16 + * @Version 1.0 + **/ +public interface InstanceService { + + GeneralResult createTable(String moduleCode, Long userId); + + GeneralResult dropTable(String moduleCode, Long userId); + + GeneralResult list(Pager pager, Long userId); + + GeneralResult create(JSONObject instance, Long userId, boolean isAutoRelation); + + GeneralResult remove(Long id, String moduleCode, Long userId); + + GeneralResult batchRemove(InstanceBean model, Long userId); + + GeneralResult modify(JSONObject instance, Long userId); + + GeneralResult batchModify(InstanceBean instanceModel, Long userId); + + GeneralResult detail(Long id, String moduleCode); + + GeneralResult export(Long moduleId, String moduleCode, String type, Long userId); + + GeneralResult download(Long moduleId, String moduleCode, String type, Long userId); + + GeneralResult upload(Long moduleId, String moduleCode, MultipartFile excel, RequestContext context); + + GeneralResult initInstance(JSONObject object, String type); + + GeneralResult topo(Long id, Long relationCategoryId, Long moduleId, Long userId); + + boolean checkAdminRole(Long userId); + + void convertInstanceValue(List> list, Long moduleId, Long userId, boolean hasAdminRole) throws Exception; + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceValueService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceValueService.java new file mode 100644 index 0000000..5d7fc3a --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/InstanceValueService.java @@ -0,0 +1,18 @@ +package com.bocloud.ams.service.instance; + +import com.megatron.common.model.GeneralResult; + +/** + * @ClassName: CmdbInstanceValueService + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 11:16 + * @Version 1.0 + **/ +public interface InstanceValueService { + + GeneralResult createTable(String moduleCode, Long userId); + + GeneralResult dropTable(String moduleCode, Long userId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAuthorityServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAuthorityServiceImpl.java new file mode 100644 index 0000000..23e2ccf --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAuthorityServiceImpl.java @@ -0,0 +1,246 @@ +package com.bocloud.ams.service.instance.impl; + +import com.bocloud.ams.entity.enums.InstanceEnum; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceAuthority; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.repository.instance.InstanceAuthorityRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceAuthorityService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.ConvertUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@Service("instanceAuthorityService") +public class InstanceAuthorityServiceImpl implements InstanceAuthorityService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceAuthorityRepository instanceAuthorityRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private RedisTemplate redisTemplate; + + @Override + public GeneralResult list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.instanceAuthorityRepository.count(pager.getParams()); + List list = this.instanceAuthorityRepository.list(pager); + for (InstanceAuthority authority : list) { + String roleName = redisTemplate.opsForValue().get("Role_Name_" + authority.getRoleId()); + if (StringUtils.isEmpty(authority.getAuths())) { + continue; + } + String[] auths = authority.getAuths().split(","); + StringBuilder authNames = new StringBuilder(); + for (String auth : auths) { + authNames.append(InstanceEnum.authority.valueOf(auth).getName() + ","); + } + authority.setUserName(redisTemplate.opsForValue().get("User_Name_" + authority.getUserId())); + authority.setRoleName(roleName); + authority.setAuthNames(authNames.substring(0, authNames.length() - 1)); + } + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Cmdb instance authority list fail:", e); + return new GeneralResult(false, "查询失败"); + } + } + + @Override + public GeneralResult create(InstanceAuthority authority, Long userId) { + try { + if ( null == authority.getInstanceIds() + || authority.getInstanceIds().isEmpty()) { + return new GeneralResult(false, "新增失败:关键属性[实例]为空"); + } + + if (StringUtils.isEmpty(authority.getAuths())) { + return new GeneralResult(false, "新增失败:关键属性[权限]为空"); + } + + if (StringUtils.isEmpty(authority.getUserIds()) + || null == authority.getRoleId()) { + return new GeneralResult(false, "新增失败:关键属性[用户]为空"); + } + List authList = new ArrayList<>(Arrays.asList(authority.getAuths().split(","))); + Long[] convert = (Long[]) ConvertUtils.convert(authority.getUserIds().split(","), Long.class); + List userIdList = new ArrayList<>(Arrays.asList(convert)); + Long moduleId = authority.getModuleId(); + Long authRoleId = authority.getRoleId(); + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return new GeneralResult(false, "新增失败:模型数据不存在"); + } + String instanceTable = CmdbUtils.CMDB_INSTANCE + module.getCode().toLowerCase(); + List addList = new ArrayList<>(); + List updateList = new ArrayList<>(); + + Map authMap = new HashMap<>(); + for (String auth : authList) { + if (!CmdbUtils.isInclude(InstanceEnum.authority.class, auth)) { + return new GeneralResult(false, "新增失败:实例权限(" + auth + ")不存在"); + } + authMap.put(auth, auth); + } + //查询实例已有权限 + List authorities = + instanceAuthorityRepository.listByInstanceId(moduleId, authority.getInstanceIds(), userIdList); + Map> instanceAuthMap = authorities.stream().collect(Collectors.groupingBy(InstanceAuthority::getInstanceId, Collectors.toList())); + for (Long instanceId : authority.getInstanceIds()) { + Instance instance = instanceRepository.query(instanceTable, instanceId); + if (null == instance) { + return new GeneralResult(false, "新增失败:实例(" + instanceId + ")数据不存在"); + } + List instanceUserAuthList = instanceAuthMap.get(instanceId); + Map userAuthMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(instanceUserAuthList)) { + userAuthMap = instanceUserAuthList.stream().collect(Collectors.toMap(InstanceAuthority::getUserId, Function.identity(), (oldData, newData) -> newData)); + } + for (Long authUserId : userIdList) { + InstanceAuthority userAuthority = userAuthMap.get(authUserId); + if (null == userAuthority) { + InstanceAuthority instanceAuthority = new InstanceAuthority(moduleId, instanceId, authRoleId, + authUserId, authority.getAuths()); + instanceAuthority.setGmtCreate(new Date()); + instanceAuthority.setCreatorId(userId); + addList.add(instanceAuthority); + } else { + userAuthority.setAuths(authority.getAuths()); + userAuthority.setRoleId(authRoleId); + userAuthority.setMenderId(userId); + userAuthority.setGmtModify(new Date()); + updateList.add(userAuthority); + } + } + } + if (addList.size() > 0) { + this.instanceAuthorityRepository.batchSave(addList, 100); + } + if (updateList.size() > 0) { + this.instanceAuthorityRepository.batchUpdate(updateList, 100); + } + return new GeneralResult(true, "新增成功"); + } catch (Exception e) { + log.error("Cmdb instance authority create error:", e); + return new GeneralResult(false, "新增失败"); + } + + } + + @Override + public GeneralResult modify(InstanceAuthority authority, Long userId) { + String path = InstanceAuthority.class.getSimpleName() + "_" + authority.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + if(StringUtils.isEmpty(authority.getAuths())){ + return new GeneralResult(false, "编辑失败:关键属性[权限]不能为空"); + } + InstanceAuthority bean = instanceAuthorityRepository.query(authority.getId()); + if (null == bean) { + return new GeneralResult(false, "编辑失败:权限关系数据不存在"); + } + CiModule module = moduleRepository.query(authority.getModuleId()); + if (null == module) { + return new GeneralResult(false, "编辑失败:模型数据不存在"); + } + bean.setAuths(authority.getAuths()); + bean.setRoleId(authority.getRoleId()); + bean.setGmtModify(new Date()); + bean.setMenderId(userId); + instanceAuthorityRepository.update(bean); + return new GeneralResult(true, "编辑成功"); + } catch (Exception e) { + log.error("Cmdb instance authority modify fail:", e); + return new GeneralResult(false, "编辑成功"); + } + } + + @Override + public GeneralResult remove(Long id, Long userId) { + String path = InstanceAuthority.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + InstanceAuthority bean = instanceAuthorityRepository.query(id); + if (null == bean) { + return new GeneralResult(false, "删除失败:实例权限关系数据不存在"); + } + instanceAuthorityRepository.remove(id, userId); + return new GeneralResult(true, "删除成功"); + } catch (Exception e) { + log.error("Cmdb instance authority remove error:", e); + return new GeneralResult(false, "删除失败"); + } + } + + @Override + public GeneralResult removeByRole(InstanceAuthority authority, Long userId) { + try { + if (null == authority.getRoleId() || null == authority.getModuleId() || null == authority.getInstanceIds() + || authority.getInstanceIds().isEmpty()) { + return new GeneralResult(false, "删除失败:未选择实例或角色为空"); + } + instanceAuthorityRepository.batchRemove(authority.getModuleId(), authority.getInstanceIds(), authority.getRoleId(), + userId); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("Cmdb instance authority removeByRole error:", e); + return new GeneralResult(false, "删除失败"); + } + } + + @Override + public GeneralResult listByInstanceId(Long moduleId, Long instanceId) { + try { + List authorities = + this.instanceAuthorityRepository.listByInstanceId(moduleId, instanceId); + for (InstanceAuthority authority : authorities) { + String roleName = redisTemplate.opsForValue().get("Role_Name_" + authority.getRoleId()); + if (StringUtils.isEmpty(authority.getAuths()) || StringUtils.isEmpty(authority.getUserIds())) { + continue; + } + String[] auths = authority.getAuths().split(","); + StringBuilder authNames = new StringBuilder(); + for (String auth : auths) { + authNames.append(InstanceEnum.authority.valueOf(auth).getName() + ","); + } + authority.setUserName(redisTemplate.opsForValue().get("User_Name_" + authority.getUserId())); + authority.setRoleName(roleName); + authority.setAuthNames(authNames.substring(0, authNames.length() - 1)); + } + return new GeneralResult(true, authorities, "查询成功"); + } catch (Exception e) { + log.error("Cmdb instance authority list error:", e); + return new GeneralResult(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAutoRelationServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAutoRelationServiceImpl.java new file mode 100644 index 0000000..5453e93 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceAutoRelationServiceImpl.java @@ -0,0 +1,209 @@ +package com.bocloud.ams.service.instance.impl; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.repository.association.AutoRelationRuleItemRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleItemValueRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleRepository; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.instance.InstanceRelationHistoryRecordRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.bocloud.ams.service.task.InstanceRelationTask; +import com.bocloud.ams.service.task.ModuleInstanceRelationTask; +import com.bocloud.ams.service.utils.RepositoryHandler; +import com.megatron.common.model.GeneralResult; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @Description: 实例自动关联接口实现 + * @Author majiali + * @CreateTime 2022/6/6 9:10 + */ +@Slf4j +@Service("instanceAutoRelationService") +public class InstanceAutoRelationServiceImpl implements InstanceAutoRelationService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private AutoRelationRuleRepository autoRelationRuleRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private AutoRelationRuleItemRepository autoRelationRuleItemRepository; + @Autowired + private AutoRelationRuleItemValueRepository autoRelationRuleItemValueRepository; + @Autowired + private InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository; + @Autowired + private RepositoryHandler handler; + @Autowired + private ThreadPoolTaskExecutor threadPoolTaskExecutor; + @Autowired + private OperationalAuditService operationalAuditService; + @Autowired + private OperationalAuditRepository operationalAuditRepository; + + @Override + public GeneralResult instanceAutoRelation(Instance instance, Long userId) { + try { + // 查询实例values + List instanceValues = instanceValueRepository.listByInstanceId(instance.getId(), + CmdbUtils.CMDB_INSTANCE_VALUE + instance.getModuleCode().toLowerCase()); + if (CollectionUtils.isEmpty(instanceValues)) { + // 当前实例没有value,不需要处理关系 + return new GeneralResult<>(false, "实例关系自动关联失败,当前实例没有值数据"); + } + instance.setInstanceValues(instanceValues); + // 根据资源数据查询模型关系 + List relations = moduleRelationRepository.queryByModuleId(instance.getModuleId()); + if (CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(false, "实例关系自动关联失败,当前实例模型没有对应的模型关系数据"); + } + List rules = autoRelationRuleRepository + .queryByModuleRelationIds(relations.stream().map(ModuleRelation::getId).collect(Collectors.toList())); + if (CollectionUtils.isEmpty(rules)) { + return new GeneralResult<>(false, "实例关系自动关联失败,当前实例模型关系没有对应的关联规则"); + } + // 关联规则item及itemvalue相关 + buildAutoRelationRuleData(rules); + Map ruleMap = + rules.stream().collect(Collectors.toMap(AutoRelationRule::getModuleRelationId, Function.identity(), (oldData, newData) -> newData)); + for (ModuleRelation relation : relations) { + // 获取模型管理规则 + AutoRelationRule rule = ruleMap.get(relation.getId()); + // 关联规则为空,不需要处理 + if (null == rule || CollectionUtils.isEmpty(rule.getItems())) { + continue; + } + InstanceRelationTask task = new InstanceRelationTask(rule, relation, instanceRelationRepository, + instanceRepository, instanceValueRepository, instanceRelationHistoryRecordRepository, handler, + instance, userId, lockFactory,operationalAuditService,operationalAuditRepository); + threadPoolTaskExecutor.execute(task); + } + } catch (Exception e) { + log.error("实例关系自动关联失败", e); + return new GeneralResult<>(false, "实例关系自动关联失败"); + } + return new GeneralResult<>(true, "实例关系自动关联任务已下发"); + } + + @Override + public GeneralResult autoRelation() { + try { + // 查询所有模型关系 + List relations = moduleRelationRepository.listAll(); + if (CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(false, "实例关系自动关联任务下发失败,模型关系不存在"); + } + List rules = autoRelationRuleRepository + .queryByModuleRelationIds(relations.stream().map(ModuleRelation::getId).collect(Collectors.toList())); + + if (CollectionUtils.isEmpty(rules)) { + return new GeneralResult<>(false, "实例关系自动关联任务下发失败,关联规则不存在"); + } + // 关联规则item及itemvalue相关 + buildAutoRelationRuleData(rules); + Map ruleMap = + rules.stream().collect(Collectors.toMap(AutoRelationRule::getModuleRelationId, Function.identity(), (oldData, newData) -> newData)); + for (ModuleRelation relation : relations) { + // 获取模型管理规则 + AutoRelationRule rule = ruleMap.get(relation.getId()); + // 关联规则为空,不需要处理 + if (null == rule || CollectionUtils.isEmpty(rule.getItems())) { + continue; + } + ModuleInstanceRelationTask task = + new ModuleInstanceRelationTask(rule, relation, instanceRelationRepository, instanceRepository, + instanceValueRepository, instanceRelationHistoryRecordRepository, handler, lockFactory,operationalAuditService,operationalAuditRepository); + threadPoolTaskExecutor.execute(task); + } + + } catch (Exception e) { + log.error("实例关系自动关联任务下发失败", e); + return new GeneralResult<>(false, "实例关系自动关联任务下发失败"); + } + return new GeneralResult<>(true, "实例关系自动关联任务已下发"); + } + + /** + * @param rules + * @throws Exception + * @Description: 查询关联规则对应的item及itemvalue相关 + */ + private void buildAutoRelationRuleData(List rules) throws Exception { + for (AutoRelationRule rule : rules) { + List items = autoRelationRuleItemRepository.queryByRuleId(rule.getId()); + for (AutoRelationRuleItem item : items) { + // 需要查询对应的字段code及类型相关值 + List values = + autoRelationRuleItemValueRepository.queryAllByItemId(item.getId()); + item.setValues(values); + } + rule.setItems(items); + } + } + + @Override + public GeneralResult autoRelationByModuleId(Long moduleId) { + try { + // 查询模型关系 + List relations = moduleRelationRepository.queryByModuleId(moduleId); + if (CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(false, "实例关系自动关联任务下发失败,模型关系不存在"); + } + List rules = autoRelationRuleRepository + .queryByModuleRelationIds(relations.stream().map(ModuleRelation::getId).collect(Collectors.toList())); + if (CollectionUtils.isEmpty(rules)) { + return new GeneralResult<>(false, "实例关系自动关联任务下发失败,关联规则不存在"); + } + // 关联规则item及itemvalue相关 + buildAutoRelationRuleData(rules); + Map ruleMap = + rules.stream().collect(Collectors.toMap(AutoRelationRule::getModuleRelationId, Function.identity(), (oldData, newData) -> newData)); + for (ModuleRelation relation : relations) { + // 获取模型管理规则 + AutoRelationRule rule = ruleMap.get(relation.getId()); + // 关联规则为空,不需要处理 + if (null == rule || CollectionUtils.isEmpty(rule.getItems())) { + continue; + } + ModuleInstanceRelationTask task = + new ModuleInstanceRelationTask(rule, relation, instanceRelationRepository, instanceRepository, + instanceValueRepository, instanceRelationHistoryRecordRepository, handler, lockFactory,operationalAuditService,operationalAuditRepository); + threadPoolTaskExecutor.execute(task); + } + } catch (Exception e) { + log.error("实例关系自动关联任务下发失败", e); + return new GeneralResult<>(false, "实例关系自动关联任务下发失败"); + } + return new GeneralResult<>(true, "实例关系自动关联任务已下发"); + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceHistoryServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceHistoryServiceImpl.java new file mode 100644 index 0000000..7135fd6 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceHistoryServiceImpl.java @@ -0,0 +1,87 @@ +package com.bocloud.ams.service.instance.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.GridHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bocloud.ams.entity.enums.InstanceEnum; +import com.bocloud.ams.entity.instance.InstanceHistory; +import com.bocloud.ams.repository.instance.InstanceHistoryRepository; +import com.bocloud.ams.service.instance.InstanceHistoryService; +import com.megatron.common.model.GeneralResult; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service("instanceHistoryService") +public class InstanceHistoryServiceImpl implements InstanceHistoryService { + + @Autowired + private InstanceHistoryRepository instanceHistoryRepository; + + @Override + public GeneralResult list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = this.instanceHistoryRepository.count(pager.getParams()); + List list = this.instanceHistoryRepository.list(pager); + for (InstanceHistory history : list) { + if (InstanceEnum.catalog.INSTANCE.name().equals(history.getCatalog())) { + history.setCatalog(InstanceEnum.catalog.INSTANCE.getValue()); + } else if (InstanceEnum.catalog.RELATION.name().equals(history.getCatalog())) { + history.setCatalog(InstanceEnum.catalog.RELATION.getValue()); + } + + if (InstanceEnum.category.CREATE.name().equals(history.getCategory())) { + history.setCategory(InstanceEnum.category.CREATE.getValue()); + } else if (InstanceEnum.category.MODIFY.name().equals(history.getCategory())) { + history.setCategory(InstanceEnum.category.MODIFY.getValue()); + } else if (InstanceEnum.category.DEL.name().equals(history.getCategory())) { + history.setCategory(InstanceEnum.category.DEL.getValue()); + } else if (InstanceEnum.category.BATCH_DELETE.name().equals(history.getCategory())) { + history.setCategory(InstanceEnum.category.BATCH_DELETE.getValue()); + } else if (InstanceEnum.category.BATCH_MODIFY.name().equals(history.getCategory())) { + history.setCategory(InstanceEnum.category.BATCH_MODIFY.getValue()); + } + } + GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Cmdb instance history list fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult create(InstanceHistory history, Long userId) { + try { + this.instanceHistoryRepository.save(history); + return new GeneralResult<>(true, "新增成功"); + } catch (Exception e) { + log.error("Cmdb instance history create error:", e); + return new GeneralResult<>(false, "新增失败"); + } + } + + @Override + public GeneralResult listByInstanceId(Long moduleId, Long instanceId) { + try { + List histories = instanceHistoryRepository.listByInstanceId(moduleId, instanceId); + return new GeneralResult<>(true, histories, "查询成功"); + } catch (Exception e) { + log.error("Cmdb instance history list error:", e); + return new GeneralResult(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationHistoryRecordServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationHistoryRecordServiceImpl.java new file mode 100644 index 0000000..cf0b0af --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationHistoryRecordServiceImpl.java @@ -0,0 +1,1148 @@ +package com.bocloud.ams.service.instance.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.InstanceRelationHistoryAlterModel; +import com.bocloud.ams.entity.model.InstanceRelationHistoryPreflightModel; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.repository.association.AutoRelationRuleRepository; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.instance.InstanceRelationHistoryRecordRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.instance.InstanceRelationHistoryRecordService; +import com.bocloud.ams.service.utils.ModuleConstant; +import com.bocloud.ams.service.utils.RelationHistoryConstant; +import com.bocloud.ams.service.utils.RepositoryHandler; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description: 实例自动关联接口实现 + * @Author majiali + * @CreateTime 2022/6/8 9:10 + */ +@Slf4j +@Service("instanceRelationHistoryRecordService") +public class InstanceRelationHistoryRecordServiceImpl implements InstanceRelationHistoryRecordService { + + @Autowired + private InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private RepositoryHandler handler; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private AutoRelationRuleRepository autoRelationRuleRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private OperationalAuditService operationalAuditService; + @Autowired + private OperationalAuditRepository operationalAuditRepository; + + @Override + public GeneralResult detail(Long id) throws Exception { + InstanceRelationHistoryRecord record = instanceRelationHistoryRecordRepository.query(id); + if (null != record) { + return new GeneralResult<>(false, "查询失败,数据不存在"); + } + return new GeneralResult<>(true, record, "查询成功"); + } + + @Override + public GeneralResult list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + pager.getSorter().put("id", Common.ONE); + int total = instanceRelationHistoryRecordRepository.count(pager.getParams()); + List list = this.instanceRelationHistoryRecordRepository.list(pager); + if (CollectionUtils.isNotEmpty(list)) { + list.forEach(template -> { + template + .setExecutor(redisTemplate.opsForValue().get("User_Name_" + template.getExecId())); + template + .setCreator(redisTemplate.opsForValue().get("User_Name_" + template.getCreatorId())); + }); + } + + GridBean bean = + new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("CmdbInstanceRelationHistoryRecord list query fail:", e); + return new GeneralResult(false, "查询失败"); + } + } + + @Override + public GeneralResult cancel(Long id, RequestContext context) { + try { + InstanceRelationHistoryRecord record = instanceRelationHistoryRecordRepository.query(id); + if (null == record) { + return new GeneralResult<>(false, "关联历史取消调和失败:数据不存在"); + } + + if (!RelationHistoryConstant.Status.RECONCILED.getValue().equals(record.getStatus())) { + return new GeneralResult<>(false, "关联历史取消调和失败:数据不是待调和状态"); + } + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.CANCEL_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(true, "关联历史取消调和成功"); + } catch (Exception e) { + log.error("CmdbInstanceRelationHistoryRecord cancel fail:", e); + return new GeneralResult<>(false, "关联历史取消调和失败"); + } + } + + @Override + public GeneralResult batchCancel(List ids, RequestContext context) { + try { + if (CollectionUtils.isEmpty(ids)) { + return new GeneralResult(false, "关联历史取消调和失败:参数异常"); + } + List records = instanceRelationHistoryRecordRepository.queryByIds(ids); + if (CollectionUtils.isEmpty(records)) { + return new GeneralResult<>(false, "关联历史取消调和失败:数据不存在"); + } + //待调和状态记录 + List reconciledRecords = new ArrayList<>(); + for (InstanceRelationHistoryRecord record : records) { + if (RelationHistoryConstant.Status.RECONCILED.getValue().equals(record.getStatus())) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.CANCEL_ERROR_MSG); + reconciledRecords.add(record); + } + } + if (CollectionUtils.isNotEmpty(reconciledRecords)) { + instanceRelationHistoryRecordRepository.batchUpdate(reconciledRecords, 100); + return new GeneralResult<>(true, "关联历史取消调和成功"); + } + return new GeneralResult<>(false, "关联历史取消调和失败,不存在待调和记录"); + + } catch (Exception e) { + log.error("CmdbInstanceRelationHistoryRecord cancel fail:", e); + return new GeneralResult<>(false, "关联历史取消调和失败"); + } + } + + @Override + public GeneralResult save(InstanceRelation instanceRelation, boolean isSource, String status, String type, String reason, + RequestContext context) { + try { + Long moduleRelationId = instanceRelation.getModuleRelationId(); + ModuleRelation moduleRelation = moduleRelationRepository.query(moduleRelationId); + if (null == moduleRelation) { + return new GeneralResult<>(false, "新增关联历史失败,模型关系不存在"); + } + AutoRelationRule relationRule = autoRelationRuleRepository.queryByModuleRelationId(moduleRelation.getId()); + InstanceRelationHistoryRecord record = + getCanceInstanceRelationHistory(isSource, moduleRelation, relationRule, + RelationHistoryConstant.Way.MANUAL.getValue(), status, type, context.getTarget(), instanceRelation); + + record.setReason(reason); + instanceRelationHistoryRecordRepository.save(record); + + return new GeneralResult<>(true, "新增关联历史成功"); + } catch (Exception e) { + return new GeneralResult<>(false, "新增关联历史失败"); + } + + } + + @Override + public GeneralResult reconcile(Long id, RequestContext context) { + try { + InstanceRelationHistoryRecord record = instanceRelationHistoryRecordRepository.query(id); + if (null == record) { + return new GeneralResult<>(false, "关联历史调和失败:数据不存在"); + } + if (!RelationHistoryConstant.Status.RECONCILED.getValue().equals(record.getStatus())) { + return new GeneralResult<>(false, "关联历史调和失败:数据不是待调和状态"); + } + // 查询当前调和记录中的模型关系,根据最新的约束条件判断当前调和记录是否可以更新 + ModuleRelation moduleRelation = moduleRelationRepository.query(record.getModuleRelationId()); + // 模型关系不存在,取消调和记录 + if (null == moduleRelation) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_MODULE_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史调和失败,模型关系不存在"); + } + + boolean isSource = record.getIsSource(); + Instance sourceInstance; + Instance targetInstance; + String sourceInstanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getSourceCode().toLowerCase(); + String targetInstanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getTargetCode().toLowerCase(); + String sourceInstanceValueTable = + CmdbUtils.CMDB_INSTANCE_VALUE + moduleRelation.getSourceCode().toLowerCase(); + String targetInstanceValueTable = + CmdbUtils.CMDB_INSTANCE_VALUE + moduleRelation.getTargetCode().toLowerCase(); + if (isSource) { + sourceInstance = instanceRepository.query(sourceInstanceTable, record.getInstanceId()); + if (null != sourceInstance) { + List sourceInstanceValues = + instanceValueRepository.listByInstanceId(record.getInstanceId(), sourceInstanceValueTable); + sourceInstance.setInstanceValues(sourceInstanceValues); + } + targetInstance = instanceRepository.query(targetInstanceTable, record.getRelationInstanceId()); + if (null != targetInstance) { + List targetInstanceValues = instanceValueRepository + .listByInstanceId(record.getRelationInstanceId(), targetInstanceValueTable); + targetInstance.setInstanceValues(targetInstanceValues); + } + } else { + sourceInstance = instanceRepository.query(sourceInstanceTable, record.getRelationInstanceId()); + if (null != sourceInstance) { + List sourceInstanceValues = instanceValueRepository + .listByInstanceId(record.getRelationInstanceId(), sourceInstanceValueTable); + sourceInstance.setInstanceValues(sourceInstanceValues); + } + targetInstance = instanceRepository.query(targetInstanceTable, record.getInstanceId()); + if (null != targetInstance) { + List targetInstanceValues = + instanceValueRepository.listByInstanceId(record.getInstanceId(), targetInstanceValueTable); + targetInstance.setInstanceValues(targetInstanceValues); + } + } + + if (null == targetInstance || null == sourceInstance) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_INSTANCE_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史调和失败,实例信息不存在"); + } + + // 取消关联 + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(record.getType())) { + return cancelRelation(record, moduleRelation, context); + } else { + return addRelation(record, moduleRelation, context); + } + } catch (Exception e) { + log.error("CmdbInstanceRelationHistoryRecord cancel fail:", e); + return new GeneralResult<>(false, "关联历史调和失败"); + } + } + + // 取消实例关系 + private GeneralResult cancelRelation(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + String props = record.getProps(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(props, InstanceRelationHistoryAlterModel.class); + List relations = alter.getBefore(); + if (CollectionUtils.isEmpty(relations)) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_INSTANCE_RELATION_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史调和失败,实例关系不存在"); + } + InstanceRelation relation = relations.get(0); + InstanceRelation tmpRelation = instanceRelationRepository.queryById(instanceRelationTable, relation.getId()); + if (null == tmpRelation) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_INSTANCE_RELATION_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史调和失败,实例关系不存在"); + } + instanceRelationRepository.remove(relation.getId(), instanceRelationTable, context.getTarget()); + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.SUCCESS.getValue(), null); + instanceRelationHistoryRecordRepository.update(record); + this.addOperationalAudit(Arrays.asList(record),context.getTarget()); + return new GeneralResult<>(true, "关联历史调和成功"); + } + + private GeneralResult addRelation(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + return dealNNReconcile(record, moduleRelation, context); + } + boolean isSource = record.getIsSource(); + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + return deal11Reconcile(record, moduleRelation, context); + } else if (isSource && ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + return dealN1PositiveReconcile(record, moduleRelation, context); + } else if (!isSource && ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + return dealN1PositiveReconcile(record, moduleRelation, context); + } else { + return dealSingleReconcile(record, moduleRelation, context); + } + + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 单条调和更新 + * @Author majiali + * @CreateTime 2022/6/14 15:16 + */ + private GeneralResult dealNNReconcile(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 当前关联的实例 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getInstanceId(), moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), record.getInstanceId()); + } + + //实例关系不存在需要新建实例关系 + if (CollectionUtils.isEmpty(relationList)) { + // 调和记录中新增关系 + InstanceRelation newRelation = alter.getAfter(); + handler.saveInstanceRelation(newRelation, instanceRelationTable); + alter.setAfter(newRelation); + record.setProps(JSONObject.toJSONString(alter)); + } + // 更新调和记录 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.SUCCESS.getValue(), null); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(true, "任务调和成功"); + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 处理存在多行调和记录冲突的预检 + * @Author majiali + * @CreateTime 2022/6/14 13:57 + */ + private GeneralResult deal11Reconcile(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 调和记录中原来有冲突关系 + List oldRelations = alter.getBefore(); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 当前关联方的实例关系 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), null); + } + //数据库中存在的当前调和记录要添加的关系 + List currList = new ArrayList<>(); + //数据库中存在冲突的实例id + List conflictList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + currList = relationList.stream().filter(item -> item.getSourceInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + conflictList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + currList = relationList.stream().filter(item -> item.getTargetInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + conflictList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + + //调和实例中记录的存在冲突的实例id + List conflictOldList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(oldRelations)) { + if (isSource) { + conflictOldList = oldRelations.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictOldList = oldRelations.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + // 数据库中存在有冲突的实例id有不在调和记录中记录的实例id,表示有冲突,手动更新 + if (chargeConflictInfo(conflictList, conflictOldList)) { + // 待调和记录手动更新失败 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "任务调和失败"); + } else { + if (CollectionUtils.isEmpty(currList)) { + // 添加关系 + // 调和记录中新增关系 + InstanceRelation newRelation = alter.getAfter(); + handler.saveInstanceRelation(newRelation, instanceRelationTable); + alter.setAfter(newRelation); + record.setProps(JSONObject.toJSONString(alter)); + } + // 更新当前调和记录 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.SUCCESS.getValue(), null); + instanceRelationHistoryRecordRepository.update(record); + if (CollectionUtils.isEmpty(currList)) { + this.addOperationalAudit(Arrays.asList(record),context.getTarget()); + } + + List delList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + delList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + } else { + delList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + } + } + + // 查询当前关系之外的其他关系 + // 当前关联的实例关系 + List currrelationList; + if (isSource) { + currrelationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getInstanceId(), moduleRelation.getTargetId(), null); + currrelationList = currrelationList.stream() + .filter(item -> !item.getTargetInstanceId().equals(record.getRelationInstanceId())) + .collect(Collectors.toList()); + } else { + currrelationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getInstanceId()); + currrelationList = currrelationList.stream() + .filter(item -> !item.getSourceInstanceId().equals(record.getRelationInstanceId())) + .collect(Collectors.toList()); + } + + delList.addAll(currrelationList); + // 删除冲突关系 + if (CollectionUtils.isNotEmpty(delList)) { + // 取消关系,增加记录 + List delIds = new ArrayList<>(); + List historyRecords = new ArrayList<>(); + AutoRelationRule relationRule = + autoRelationRuleRepository.queryByModuleRelationId(moduleRelation.getId()); + for (InstanceRelation del : delList) { + historyRecords.add(getCanceInstanceRelationHistory(isSource, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.CANCEL.getValue(), context.getTarget(), del)); + delIds.add(del.getId()); + } + instanceRelationRepository.removeByIds(delIds, instanceRelationTable, context.getTarget()); + instanceRelationHistoryRecordRepository.batchSave(historyRecords, 100); + this.addOperationalAudit(historyRecords,context.getTarget()); + + } + + //除了当前待调和记录外的其他待调和记录(同一个模型关系下)标记为失败 + List recordList = + instanceRelationHistoryRecordRepository.queryByCondition(record.getInstanceId(), + record.getModuleId(), RelationHistoryConstant.Status.RECONCILED.getValue(), record.getModuleRelationId()); + //当前调和记录已经更新了状态,待调和记录中查询不到了 + //recordList.remove(record); + if (CollectionUtils.isNotEmpty(recordList)) { + for (InstanceRelationHistoryRecord record1 : recordList) { + setExecInfo(record1, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + } + instanceRelationHistoryRecordRepository.batchUpdate(recordList, 100); + } + + return new GeneralResult<>(true, "任务调和成功"); + } + + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: N-1处理存在多行调和记录冲突的预检 + * @Author majiali + * @CreateTime 2022/6/14 13:57 + */ + private GeneralResult dealN1PositiveReconcile(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + //数据库中存在的当前调和记录要添加的关系 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getInstanceId(), moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), record.getInstanceId()); + } + + if (CollectionUtils.isEmpty(relationList)) { + // 添加关系 + // 调和记录中新增关系 + InstanceRelation newRelation = alter.getAfter(); + handler.saveInstanceRelation(newRelation, instanceRelationTable); + alter.setAfter(newRelation); + record.setProps(JSONObject.toJSONString(alter)); + } + // 更新当前调和记录 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.SUCCESS.getValue(), null); + instanceRelationHistoryRecordRepository.update(record); + if (CollectionUtils.isEmpty(relationList)) { + this.addOperationalAudit(Arrays.asList(record), context.getTarget()); + } + + // 查询当前关系之外的其他关系(需要删除的关系) + List currrelationList; + if (isSource) { + currrelationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getInstanceId(), moduleRelation.getTargetId(), null); + currrelationList = currrelationList.stream() + .filter(item -> !item.getTargetInstanceId().equals(record.getRelationInstanceId())) + .collect(Collectors.toList()); + } else { + currrelationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getInstanceId()); + currrelationList = currrelationList.stream() + .filter(item -> !item.getSourceInstanceId().equals(record.getRelationInstanceId())) + .collect(Collectors.toList()); + } + if (CollectionUtils.isNotEmpty(currrelationList)) { + // 取消关系,增加记录 + List delIds = new ArrayList<>(); + List historyRecords = new ArrayList<>(); + AutoRelationRule relationRule = + autoRelationRuleRepository.queryByModuleRelationId(moduleRelation.getId()); + for (InstanceRelation del : currrelationList) { + historyRecords.add(getCanceInstanceRelationHistory(isSource, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.CANCEL.getValue(), context.getTarget(), del)); + delIds.add(del.getId()); + } + instanceRelationRepository.removeByIds(delIds, instanceRelationTable, context.getTarget()); + instanceRelationHistoryRecordRepository.batchSave(historyRecords, 100); + this.addOperationalAudit(historyRecords,context.getTarget()); + + } + //除了当前待调和记录外的其他待调和记录(同一个模型关系下)标记为失败 + List recordList = + instanceRelationHistoryRecordRepository.queryByCondition(record.getInstanceId(), + record.getModuleId(), RelationHistoryConstant.Status.RECONCILED.getValue(), record.getModuleRelationId()); + //当前调和记录已经更新了状态,待调和记录中查询不到了 + //recordList.remove(record); + if (CollectionUtils.isNotEmpty(recordList)) { + for (InstanceRelationHistoryRecord record1 : recordList) { + setExecInfo(record1, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + } + instanceRelationHistoryRecordRepository.batchUpdate(recordList, 100); + } + + return new GeneralResult<>(true, "任务调和成功"); + + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 单条调和更新 + * @Author majiali + * @CreateTime 2022/6/14 15:16 + */ + private GeneralResult dealSingleReconcile(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 调和记录中原来有冲突关系 + List oldRelations = alter.getBefore(); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 当前关联的实例 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), null); + } + //数据库中存在的当前调和记录要添加的关系 + List currList = new ArrayList<>(); + //数据库中存在冲突的实例id + List conflictList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + currList = relationList.stream().filter(item -> item.getSourceInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + conflictList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + currList = relationList.stream().filter(item -> item.getTargetInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + conflictList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + + List conflictOldList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(oldRelations)) { + if (isSource) { + conflictOldList = oldRelations.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictOldList = oldRelations.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + // 有冲突,手动更新 + if (chargeConflictInfo(conflictList, conflictOldList)) { + // 待调和记录手动更新失败 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "任务调和失败"); + } else { + if (CollectionUtils.isEmpty(currList)) { + // 添加关系 + // 调和记录中新增关系 + InstanceRelation newRelation = alter.getAfter(); + handler.saveInstanceRelation(newRelation, instanceRelationTable); + alter.setAfter(newRelation); + record.setProps(JSONObject.toJSONString(alter)); + } + // 更新调和记录 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.SUCCESS.getValue(), null); + instanceRelationHistoryRecordRepository.update(record); + if (CollectionUtils.isEmpty(currList)) { + this.addOperationalAudit(Arrays.asList(record), context.getTarget()); + } + // 删除冲突关系 + if (CollectionUtils.isNotEmpty(relationList)) { + List delList; + if (isSource) { + delList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + } else { + delList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .collect(Collectors.toList()); + } + if (CollectionUtils.isNotEmpty(delList)) { + // 取消关系,增加记录 + List delIds = new ArrayList<>(); + List historyRecords = new ArrayList<>(); + AutoRelationRule relationRule = + autoRelationRuleRepository.queryByModuleRelationId(moduleRelation.getId()); + for (InstanceRelation del : delList) { + historyRecords.add(getCanceInstanceRelationHistory(isSource, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.CANCEL.getValue(), context.getTarget(), del)); + delIds.add(del.getId()); + } + instanceRelationHistoryRecordRepository.batchSave(historyRecords, 100); + instanceRelationRepository.removeByIds(delIds, instanceRelationTable, context.getTarget()); + this.addOperationalAudit(historyRecords,context.getTarget()); + } + } + return new GeneralResult<>(true, "任务调和成功"); + } + } + + private InstanceRelationHistoryRecord getCanceInstanceRelationHistory(boolean isPositive, + ModuleRelation moduleRelation, AutoRelationRule relationRule, String way, String status, String type, + Long userId, InstanceRelation oldRelation) { + InstanceRelationHistoryRecord record = new InstanceRelationHistoryRecord(); + InstanceRelationHistoryAlterModel alter = new InstanceRelationHistoryAlterModel(); + // 当前实例是源实例 + if (isPositive) { + record.setName(oldRelation.getSourceInstanceName()); + record.setInstanceId(oldRelation.getSourceInstanceId()); + record.setModuleId(oldRelation.getSourceModuleId()); + record.setRelationInstanceId(oldRelation.getTargetInstanceId()); + record.setModuleName(moduleRelation.getSourceName()); + + } else { + record.setName(oldRelation.getTargetInstanceName()); + record.setInstanceId(oldRelation.getTargetInstanceId()); + record.setModuleId(oldRelation.getTargetModuleId()); + record.setRelationInstanceId(oldRelation.getSourceInstanceId()); + record.setModuleName(moduleRelation.getTargetName()); + } + // 取消关联 + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(type)) { + record.setAlterAfter("--"); + record.setAlterBefore(oldRelation.getSourceInstanceName() + "->" + oldRelation.getTargetInstanceName()); + alter.setBefore(Arrays.asList(oldRelation)); + } else { + record.setAlterBefore("--"); + record.setAlterAfter(oldRelation.getSourceInstanceName() + "->" + oldRelation.getTargetInstanceName()); + alter.setAfter(oldRelation); + } + if (null != relationRule) { + record.setAutoRelationRuleId(relationRule.getId()); + } + record.setRelationCategoryId(moduleRelation.getRelationCategoryId()); + record.setModuleRelationId(moduleRelation.getId()); + record.setIsSource(isPositive); + record.setProps(JSONObject.toJSONString(alter)); + record.setDeleted(false); + record.setCreatorId(userId); + record.setGmtCreate(new Date()); + record.setWay(way); + record.setStatus(status); + record.setType(type); + record.setExecTime(new Date()); + record.setExecId(userId); + return record; + } + + @Override + public GeneralResult preflight(Long id, RequestContext context) { + try { + InstanceRelationHistoryPreflightModel model = new InstanceRelationHistoryPreflightModel(); + InstanceRelationHistoryRecord record = instanceRelationHistoryRecordRepository.query(id); + if (null == record) { + return new GeneralResult<>(false, "关联历史预检失败:数据不存在"); + } + if (!RelationHistoryConstant.Status.RECONCILED.getValue().equals(record.getStatus())) { + return new GeneralResult<>(false, "关联历史预检失败:数据不是待调和状态"); + } + // 查询当前调和记录中的模型关系,根据最新的约束条件判断当前调和记录是否可以更新 + ModuleRelation moduleRelation = moduleRelationRepository.query(record.getModuleRelationId()); + // 模型关系不存在,取消调和记录 + if (null == moduleRelation) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_MODULE_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史预检失败,模型关系不存在"); + } + // 取消关联--调和中的记录应该没有取消关联类型 + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(record.getType())) { + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "关联历史预检成功"); + } + boolean isSource = record.getIsSource(); + Instance sourceInstance; + Instance targetInstance; + String sourceInstanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getSourceCode().toLowerCase(); + String targetInstanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getTargetCode().toLowerCase(); + String sourceInstanceValueTable = + CmdbUtils.CMDB_INSTANCE_VALUE + moduleRelation.getSourceCode().toLowerCase(); + String targetInstanceValueTable = + CmdbUtils.CMDB_INSTANCE_VALUE + moduleRelation.getTargetCode().toLowerCase(); + if (isSource) { + sourceInstance = instanceRepository.query(sourceInstanceTable, record.getInstanceId()); + if (null != sourceInstance) { + List sourceInstanceValues = + instanceValueRepository.listByInstanceId(record.getInstanceId(), sourceInstanceValueTable); + sourceInstance.setInstanceValues(sourceInstanceValues); + } + targetInstance = instanceRepository.query(targetInstanceTable, record.getRelationInstanceId()); + if (null != targetInstance) { + List targetInstanceValues = instanceValueRepository + .listByInstanceId(record.getRelationInstanceId(), targetInstanceValueTable); + targetInstance.setInstanceValues(targetInstanceValues); + } + } else { + sourceInstance = instanceRepository.query(sourceInstanceTable, record.getRelationInstanceId()); + if (null != sourceInstance) { + List sourceInstanceValues = instanceValueRepository + .listByInstanceId(record.getRelationInstanceId(), sourceInstanceValueTable); + sourceInstance.setInstanceValues(sourceInstanceValues); + } + targetInstance = instanceRepository.query(targetInstanceTable, record.getInstanceId()); + if (null != targetInstance) { + List targetInstanceValues = + instanceValueRepository.listByInstanceId(record.getInstanceId(), targetInstanceValueTable); + targetInstance.setInstanceValues(targetInstanceValues); + } + } + + if (null == targetInstance || null == sourceInstance) { + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.NO_INSTANCE_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, "关联历史预检失败,实例信息不存在"); + } + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + //N-N关系是可以直接添加关系的。会出现调和记录一般为约束条件1-N或者1-1改为N-N引起的。(调和记录为1-N或1-1的时候产生的) + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "关联历史预检成功"); + } + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + return deal11Preflight(record, moduleRelation, context); + } else if (isSource && ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + return dealN1PositivePreflight(record, moduleRelation, context); + } else if (!isSource && ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + return dealN1PositivePreflight(record, moduleRelation, context); + } else { + return dealSinglePreflight(record, moduleRelation, context); + } + + } catch (Exception e) { + log.error("CmdbInstanceRelationHistoryRecord preflight fail:", e); + return new GeneralResult<>(false, "关联历史预检失败"); + } + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 单条记录预检 + * @Author majiali + * @CreateTime 2022/6/14 13:55 + */ + private GeneralResult dealSinglePreflight(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + InstanceRelationHistoryPreflightModel model = new InstanceRelationHistoryPreflightModel(); + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 调和记录中原来有冲突关系 + List oldRelations = alter.getBefore(); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 当前关联的实例 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), null); + } + List conflictList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + conflictList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + + List conflictOldList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(oldRelations)) { + if (isSource) { + conflictOldList = oldRelations.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictOldList = oldRelations.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + // 有冲突,手动更新 + if (chargeConflictInfo(conflictList, conflictOldList)) { + model.setStatus(RelationHistoryConstant.Status.FAILED.getValue()); + // 待调和记录手动更新失败 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(false, model, RelationHistoryConstant.RECONCILED_ERROR_MSG); + } else { + // 预检成功 + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } + + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 1-1关系预检处理存在多行调和记录冲突的预检 + * @Author majiali + * @CreateTime 2022/6/14 13:57 + */ + private GeneralResult deal11Preflight(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + InstanceRelationHistoryPreflightModel model = new InstanceRelationHistoryPreflightModel(); + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 调和记录中原来有冲突关系 + List oldRelations = alter.getBefore(); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 当前关联的实例 + List relationList; + if (isSource) { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), record.getRelationInstanceId()); + } else { + relationList = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), record.getRelationInstanceId(), moduleRelation.getTargetId(), null); + } + List conflictList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + conflictList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + + List conflictOldList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(oldRelations)) { + if (isSource) { + conflictOldList = oldRelations.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictOldList = oldRelations.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + + // 当前调和记录是否有冲突,手动更新 + if (chargeConflictInfo(conflictList, conflictOldList)) { + model.setStatus(RelationHistoryConstant.Status.FAILED.getValue()); + // 待调和记录手动更新失败 + setExecInfo(record, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + instanceRelationHistoryRecordRepository.update(record); + return new GeneralResult<>(true, model, RelationHistoryConstant.RECONCILED_ERROR_MSG); + } + + // 除了当前待调和记录外的其他待调和记录(同一个模型关系下) + List recordList = instanceRelationHistoryRecordRepository.queryByCondition( + record.getInstanceId(), record.getModuleId(), RelationHistoryConstant.Status.RECONCILED.getValue(), record.getModuleRelationId()); + recordList.remove(record); + + if (CollectionUtils.isEmpty(recordList)) { + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } + + List relationIds = recordList.stream().map(InstanceRelationHistoryRecord::getRelationInstanceId).collect(Collectors.toList()); + // 当前关联的实例 + List ralationList; + if (isSource) { + ralationList = instanceRelationRepository.queryByInstanceIds(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), relationIds); + } else { + ralationList = instanceRelationRepository.queryByInstanceIds(instanceRelationTable, + moduleRelation.getSourceId(), relationIds, moduleRelation.getTargetId(), null); + } + + Map> relationMap; + if (isSource) { + relationMap = ralationList.stream().collect(Collectors.groupingBy(InstanceRelation::getTargetInstanceId)); + } else { + relationMap = ralationList.stream().collect(Collectors.groupingBy(InstanceRelation::getSourceInstanceId)); + } + List successList = new ArrayList<>(); + successList.add(record); + List failedList = new ArrayList<>(); + for (InstanceRelationHistoryRecord historyRecord : recordList) { + if (singlePreflight(historyRecord, moduleRelation, + relationMap.get(historyRecord.getRelationInstanceId()))) { + // 待调和记录手动更新失败 + setExecInfo(historyRecord, context.getTarget(), RelationHistoryConstant.Status.FAILED.getValue(), RelationHistoryConstant.RECONCILED_ERROR_MSG); + failedList.add(historyRecord); + } else { + // 预检成功的记录 + successList.add(historyRecord); + } + } + if (CollectionUtils.isNotEmpty(failedList)) { + instanceRelationHistoryRecordRepository.batchUpdate(failedList, 100); + } + if (successList.size() > 1) { + model.setSourceType(moduleRelation.getSourceType()); + model.setTargetType(moduleRelation.getTargetType()); + model.setHistoryRecordList(successList); + model.setStatus(RelationHistoryConstant.Status.RECONCILED.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } else { + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } + } + + /** + * @param record + * @param moduleRelation + * @param context + * @Description: 正向N-1处理存在多行调和记录冲突的预检 + * @Author majiali + * @CreateTime 2022/6/14 13:57 + */ + private GeneralResult dealN1PositivePreflight(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + RequestContext context) throws Exception { + InstanceRelationHistoryPreflightModel model = new InstanceRelationHistoryPreflightModel(); + + // 除了当前待调和记录外的其他待调和记录(同一个模型关系下) + List recordList = instanceRelationHistoryRecordRepository.queryByCondition( + record.getInstanceId(), record.getModuleId(), RelationHistoryConstant.Status.RECONCILED.getValue(), record.getModuleRelationId()); + //只有一条调和记录。预检成功 + if (CollectionUtils.isEmpty(recordList)) { + return new GeneralResult<>(false, "调和任务预检失败,数据异常"); + } + if (recordList.size() == 1) { + model.setStatus(RelationHistoryConstant.Status.SUCCESS.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } else { + model.setSourceType(moduleRelation.getSourceType()); + model.setTargetType(moduleRelation.getTargetType()); + model.setHistoryRecordList(recordList); + model.setStatus(RelationHistoryConstant.Status.RECONCILED.getValue()); + return new GeneralResult<>(true, model, "调和任务预检成功"); + } + } + + private boolean singlePreflight(InstanceRelationHistoryRecord record, ModuleRelation moduleRelation, + List relationList) throws Exception { + boolean isSource = record.getIsSource(); + InstanceRelationHistoryAlterModel alter = JSONObject.parseObject(record.getProps(), InstanceRelationHistoryAlterModel.class); + // 调和记录中原来有冲突关系 + List oldRelations = alter.getBefore(); + List conflictList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(relationList)) { + if (isSource) { + conflictList = relationList.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictList = relationList.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + List conflictOldList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(oldRelations)) { + if (isSource) { + conflictOldList = oldRelations.stream().filter(item -> !item.getSourceInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList()); + } else { + conflictOldList = oldRelations.stream().filter(item -> !item.getTargetInstanceId().equals(record.getInstanceId())) + .map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList()); + } + } + return chargeConflictInfo(conflictList, conflictOldList); + } + + /** + * @param conflictList 现有冲突的关联实例id + * @param conflictOldList 调和记录中记录的关联实例id + * @Description: 判断现有冲突的关联实例id与调和记录中记录的关联实例id是否有冲突 conflictList中移除了conflictOldList + * @Author majiali + * @CreateTime 2022/6/14 11:05 + */ + private boolean chargeConflictInfo(List conflictList, List conflictOldList) { + if (CollectionUtils.isEmpty(conflictList)) { + return false; + } + // 现有 + conflictList.removeAll(conflictOldList); + if (CollectionUtils.isEmpty(conflictList)) { + return false; + } + return true; + } + + /** + * @param record 关联历史记录 + * @param userId 操作人 + * @Description: 设置关联历史的执行信息 + * @Author majiali + * @CreateTime 2022/6/16 11:25 + */ + private void setExecInfo(InstanceRelationHistoryRecord record, Long userId, String status, String reason) { + record.setExecId(userId); + record.setExecTime(new Date()); + record.setGmtModify(new Date()); + record.setMenderId(userId); + record.setStatus(status); + record.setReason(reason); + } + + //操作审计 + private void addOperationalAudit(List list,Long userId) { + try { + List auditList = new ArrayList<>(); + for (InstanceRelationHistoryRecord historyRecord : list) { + if(!RelationHistoryConstant.Status.SUCCESS.getValue().equals(historyRecord.getStatus())){ + continue; + } + String props = historyRecord.getProps(); + //关联 + InstanceRelationHistoryAlterModel alter = null; + if (StringUtils.isNotEmpty(props)) { + alter = JSONObject.parseObject(historyRecord.getProps(), InstanceRelationHistoryAlterModel.class); + } + //关联 + Map afterMap = null; + Map beforeMap = null; + OperationalAudit audit = null; + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(historyRecord.getType())) { + + if (null != alter && CollectionUtils.isNotEmpty(alter.getBefore())) { + beforeMap = JSON.parseObject(JSON.toJSONString(alter.getBefore().get(0)), new TypeReference>() { + }); + } + audit = operationalAuditService.buildLog(OperationalAuditType.ASSOCIATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getInstanceId(), userId, beforeMap, afterMap); + + } else { + if (null != alter && null != alter.getAfter()) { + afterMap = + JSON.parseObject(JSON.toJSONString(alter.getAfter()), new TypeReference>() { + }); + } + + audit = operationalAuditService.buildLog(OperationalAuditType.RELATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getInstanceId(), userId, beforeMap, afterMap); + } + + auditList.add(audit); + } + + if(!auditList.isEmpty()){ + operationalAuditRepository.batchSave(auditList, 100); + } + + }catch (Exception e){ + log.error("记录操作审计信息异常",e); + } + + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationServiceImpl.java new file mode 100644 index 0000000..4192ed8 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceRelationServiceImpl.java @@ -0,0 +1,363 @@ +package com.bocloud.ams.service.instance.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.enums.InstanceEnum; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.repository.association.AutoRelationRuleItemRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleItemValueRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleRepository; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.*; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.instance.InstanceRelationHistoryRecordService; +import com.bocloud.ams.service.instance.InstanceRelationService; +import com.bocloud.ams.service.utils.*; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Author liuyuanyuan + * @Date 2022/5/16 0016 14:25 + * @Description: + */ +@Slf4j +@Service("instanceRelationService") +public class InstanceRelationServiceImpl implements InstanceRelationService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private AutoRelationRuleRepository autoRelationRuleRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private AutoRelationRuleItemRepository autoRelationRuleItemRepository; + @Autowired + private AutoRelationRuleItemValueRepository autoRelationRuleItemValueRepository; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private PropertyItemRepository propertyItemRepository; + @Autowired + private RepositoryHandler handler; + @Autowired + private InstanceHistoryHelper instanceHistoryHelper; + @Autowired + private OperationalAuditRepository operationalAuditRepository; + @Autowired + private OperationalAuditService operationalAuditService; + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private InstanceRelationHistoryRecordService instanceRelationHistoryRecordService; + @Autowired + private ModuleRepository moduleRepository; + + @Override + public GeneralResult createTable(String relationCategoryCode, Long userId) throws Exception { + try { + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategoryCode.toLowerCase(); + if (instanceRelationRepository.countTable(relationTable) > 0) { + log.error("创建CI实例关系表{}失败", relationTable); + throw new Exception("创建CI实例关系表失败"); + // return new GeneralResult<>(false, "创建失败"); + } + instanceRelationRepository.createTable(relationTable, new InstanceRelation()); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("create module instance table error:", e); + throw new Exception("创建CI实例关系表失败"); + // return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + public GeneralResult dropTable(String relationCategoryCode, Long userId) throws Exception { + try { + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategoryCode.toLowerCase(); + if (instanceRelationRepository.countTable(relationTable) == 0) { + log.warn("删除表空间{}失败", relationTable); + // return new GeneralResult<>(false, "删除失败"); + throw new Exception("删除CI实例关系表失败"); + } + instanceRelationRepository.dropTable(relationTable); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("drop module instance table error:", e); + throw new Exception("删除CI实例关系表失败"); + // return new GeneralResult<>(false, "删除失败"); + } + } + + @Override + public GeneralResult create(InstanceRelation instanceRelation, RequestContext context) { + Long relationCategoryId = instanceRelation.getRelationCategoryId(); + Long moduleRelationId = instanceRelation.getModuleRelationId(); + + Long sourceModuleId = instanceRelation.getSourceModuleId(); + String sourceModuleCode = instanceRelation.getSourceModuleCode(); + Long sourceInstanceId = instanceRelation.getSourceInstanceId(); + + Long targetModuleId = instanceRelation.getTargetModuleId(); + Long targetInstanceId = instanceRelation.getTargetInstanceId(); + String targetModuleCode = instanceRelation.getTargetModuleCode(); + + Long currentModuleId = instanceRelation.getCurrentModuleId(); + Long currentInstanceId = instanceRelation.getCurrentInstanceId(); + //判断是否为源 + boolean isSource = false; + if ((currentModuleId + "-" + currentInstanceId).equals(sourceModuleId + "-" + sourceInstanceId)) { + isSource = true; + } + instanceRelation.setWay(RelationHistoryConstant.Way.MANUAL.getValue()); + try { + RelationCategory relationCategory = relationCategoryRepository.query(relationCategoryId); + if (null == relationCategory) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "关系分组不存在", context); + return new GeneralResult<>(false, "关系分组不存在"); + } + instanceRelation.setRelationCategoryCode(relationCategory.getCode()); + + ModuleRelation moduleRelation = + moduleRelationRepository.query(relationCategoryId, sourceModuleId, targetModuleId); + if (null == moduleRelation) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "模型关系不存在", context); + return new GeneralResult<>(false, "模型关系不存在"); + } + instanceRelation.setModuleRelationName(moduleRelation.getName()); + //封装校验是否符合实例关系数据 + //源实例 + String sourceIntanceTable = CmdbUtils.CMDB_INSTANCE + sourceModuleCode.toLowerCase(); + String sourceIntanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + sourceModuleCode.toLowerCase(); + Instance sourceInstance = instanceRepository.query(sourceIntanceTable, sourceInstanceId); + List sourceInstanceValues = instanceValueRepository.listByInstanceId(sourceInstanceId, sourceIntanceValueTable); + if (null == sourceInstance || CollectionUtils.isEmpty(sourceInstanceValues)) { + return new GeneralResult<>(false, "模型关系中源实例不存在"); + } + sourceInstance.setInstanceValues(sourceInstanceValues); + for (InstanceValue instanceValue : sourceInstanceValues) { + if (Common.NAME.equals(instanceValue.getPropertyCode())) { + instanceRelation.setSourceInstanceName(instanceValue.getPropertyValue()); + break; + } + } + //目标实例 + String targetIntanceTable = CmdbUtils.CMDB_INSTANCE + targetModuleCode.toLowerCase(); + String targetIntanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + targetModuleCode.toLowerCase(); + Instance targetInstance = instanceRepository.query(targetIntanceTable, targetInstanceId); + List targetnstanceValues = instanceValueRepository.listByInstanceId(targetInstanceId, targetIntanceValueTable); + if (null == targetInstance || CollectionUtils.isEmpty(targetnstanceValues)) { + return new GeneralResult<>(false, "模型关系中目标实例不存在"); + } + targetInstance.setInstanceValues(targetnstanceValues); + for (InstanceValue instanceValue : targetnstanceValues) { + if (Common.NAME.equals(instanceValue.getPropertyCode())) { + instanceRelation.setTargetInstanceName(instanceValue.getPropertyValue()); + break; + } + } + // 检验是否满足模型关系 + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(); + String instanceRelationType = sourceType + "-" + targetType; + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + InstanceRelation sourceInstanceRelation = instanceRelationRepository.querySource(relationTable, sourceModuleId, sourceInstanceId, targetModuleId); + InstanceRelation targetInstanceRelation = instanceRelationRepository.queryTarget(relationTable, targetModuleId, targetInstanceId, sourceModuleId); + if (null != sourceInstanceRelation || null != targetInstanceRelation) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "模型实例已关联,模型关系" + instanceRelationType, context); + return new GeneralResult<>(false, "模型实例已关联,模型关系" + instanceRelationType); + } + + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + InstanceRelation sourceInstanceRelation = + instanceRelationRepository.querySource(relationTable, sourceModuleId, sourceInstanceId, targetModuleId); + if (null != sourceInstanceRelation) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "模型实例已关联,模型关系" + instanceRelationType, context); + return new GeneralResult<>(false, "模型实例已关联,模型关系" + instanceRelationType); + } + } else if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + InstanceRelation targetInstanceRelation = + instanceRelationRepository.queryTarget(relationTable, targetModuleId, targetInstanceId, sourceModuleId); + if (null != targetInstanceRelation) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "模型实例已关联,模型关系" + instanceRelationType, context); + return new GeneralResult<>(false, "模型实例已关联,模型关系" + instanceRelationType); + } + } + // 判断模型关联规则 + AutoRelationRule rule = autoRelationRuleRepository.queryByModuleRelationId(moduleRelationId); + // 当存在关联规则则需要验证规则对应项 + if (null != rule) { + List items = autoRelationRuleItemRepository.queryByRuleId(rule.getId()); + for (AutoRelationRuleItem item : items) { + // 需要查询对应的字段code及类型相关值 + List values = + autoRelationRuleItemValueRepository.queryAllByItemId(item.getId()); + item.setValues(values); + } + rule.setItems(items); + // 是否满足 + boolean isSatisfied = AutoModuleInstanceRelationUtils.isInstanceRelation(sourceInstance, targetInstance, rule); + if (!isSatisfied) { + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + "模型实例关系不符合对应关联规则", context); + return new GeneralResult<>(false, "模型实例关系不符合对应关联规则"); + } + } + instanceRelation.setDeleted(false); + instanceRelation.setCreatorId(context.getTarget()); + instanceRelation.setGmtCreate(new Date()); + handler.saveInstanceRelation(instanceRelation, relationTable); + // 关联记录 + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.SUCCESS.name(), RelationHistoryConstant.Type.RELATION.name(), "关联成功", + context); + // 操作记录 + instanceHistoryHelper.history(instanceRelation, InstanceEnum.catalog.RELATION.name(), + InstanceEnum.category.CREATE.name(), context.getTarget()); + + addOperationalAudit(isSource,instanceRelation,RelationHistoryConstant.Type.RELATION.name(),context.getTarget()); + return new GeneralResult<>(true, "关联成功"); + } catch (Exception e) { + log.error("instance relation create fail:", e); + // 关联记录 + instanceRelationHistoryRecordService.save(instanceRelation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.RELATION.name(), + e.getMessage(), context); + return new GeneralResult<>(false, "关联异常"); + } + } + + @Override + public GeneralResult remove(Long id, String categoryCode, Long currentModuleId, Long currentInstanceId, RequestContext context) { + String path = InstanceRelation.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + RelationCategory category = relationCategoryRepository.queryByCode(categoryCode); + if (null == category) { + return new GeneralResult<>(false, "关系分组不存在"); + } + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + categoryCode.toLowerCase(); + InstanceRelation relation = instanceRelationRepository.queryById(relationTable, id); + if (null == relation) { + return new GeneralResult<>(false, "模型实例关系不存在"); + } + //手工取消 + relation.setWay(RelationHistoryConstant.Way.MANUAL.getValue()); + boolean isSource = (currentModuleId + "-" + currentInstanceId).equals(relation.getSourceModuleId() + "-" + relation.getSourceInstanceId()); + boolean result = instanceRelationRepository.remove(id, relationTable, context.getTarget()); + // 关联记录 + if (result) { + instanceRelationHistoryRecordService.save(relation, isSource, + RelationHistoryConstant.Status.SUCCESS.name(), RelationHistoryConstant.Type.CANCEL.name(), "取消关联成功", + context); + } else { + instanceRelationHistoryRecordService.save(relation, isSource, + RelationHistoryConstant.Status.FAILED.name(), RelationHistoryConstant.Type.CANCEL.name(), "取消关联失败", + context); + } + instanceHistoryHelper.history(relation, InstanceEnum.catalog.RELATION.name(), + InstanceEnum.category.DEL.name(), context.getTarget()); + addOperationalAudit(isSource,relation,RelationHistoryConstant.Type.CANCEL.name(),context.getTarget()); + return new GeneralResult<>(true, "取消关联成功"); + } catch (Exception e) { + log.error("instance relation remove fail:", e); + return new GeneralResult<>(false, "取消关联异常"); + } + } + //增加审计日志 + private void addOperationalAudit(boolean isSource,InstanceRelation relation,String type,Long userId) { + + try { + // 操作审计 + Map afterMap = null; + Map beforeMap = null; + OperationalAuditType auditType; + OperationalAudit audit; + CiModule module; + //取消关联 + if (RelationHistoryConstant.Type.CANCEL.name().equals(type)) { + auditType = OperationalAuditType.ASSOCIATION; + beforeMap = JSON.parseObject(JSON.toJSONString(relation), new TypeReference>() { + }); + } else { + auditType = OperationalAuditType.RELATION; + afterMap = JSON.parseObject(JSON.toJSONString(relation), new TypeReference>() { + }); + + } + + String moduleName = ""; + if (isSource) { + module = moduleRepository.query(relation.getSourceModuleId()); + if (null != module) { + moduleName = module.getName(); + } + audit = operationalAuditService.buildLog(auditType, moduleName, + relation.getSourceInstanceName(), relation.getSourceModuleCode(), + relation.getSourceInstanceId(), userId, beforeMap, afterMap); + } else { + module = moduleRepository.query(relation.getTargetModuleId()); + if (null != module) { + moduleName = module.getName(); + } + audit = operationalAuditService.buildLog(auditType, moduleName, + relation.getTargetInstanceName(), relation.getTargetModuleCode(), + relation.getTargetInstanceId(), userId, beforeMap, afterMap); + } + + operationalAuditRepository.save(audit); + } catch (Exception e) { + log.error("记录操作审计信息异常", e); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceServiceImpl.java new file mode 100644 index 0000000..502aaf8 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceServiceImpl.java @@ -0,0 +1,2369 @@ +package com.bocloud.ams.service.instance.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.bocloud.ams.entity.Role; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.collection.CollectionTask; +import com.bocloud.ams.entity.enums.InstanceEnum; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.entity.instance.*; +import com.bocloud.ams.entity.model.*; +import com.bocloud.ams.entity.module.*; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.collection.CollectionTaskRepository; +import com.bocloud.ams.repository.instance.*; +import com.bocloud.ams.repository.module.*; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.bocloud.ams.service.instance.InstanceService; +import com.bocloud.ams.service.instance.InstanceValueService; +import com.bocloud.ams.service.internal.SmsInternalService; +import com.bocloud.ams.service.module.PropertyService; +import com.bocloud.ams.service.utils.*; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.megatron.common.encrypt.AESEncryptor; +import com.megatron.common.encrypt.Encryptor; +import com.megatron.common.model.*; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.IDFactory; +import com.megatron.common.utils.JSONTools; +import com.megatron.common.utils.ListTool; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.URLDecoder; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @ClassName: CmdbInstanceServiceImpl + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 11:25 + * @Version 1.0 + **/ +@Slf4j +@Service("instanceService") +public class InstanceServiceImpl implements InstanceService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private InstanceValueService instanceValueService; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private PropertyItemRepository propertyItemRepository; + @Autowired + private RegularExpressionRepository regularExpressionRepository; + @Autowired + private InstanceAuthorityRepository instanceAuthorityRepository; + @Autowired + private SmsInternalService smsInternalService; + @Autowired + private InstanceHistoryHelper instanceHistoryHelper; + @Autowired + private InstanceHistoryRepository instanceHistoryRepository; + @Autowired + private RepositoryHandler handler; + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + @Autowired + private InstanceExcelHelper excelHelper; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private OperationalAuditRepository operationalAuditRepository; + @Autowired + private OperationalAuditService operationalAuditService; + @Autowired + private InstanceAutoRelationService instanceAutoRelationService; + @Autowired + private PropertyService propertyService; + @Autowired + PropertyGroupRepository propertyGroupRepository; + @Autowired + private CollectionTaskRepository collectionTaskRepository; + + @Autowired + private EventPublisher eventPublisher; + double progressLast = 0L; + + @Override + public GeneralResult createTable(String moduleCode, Long userId) { + try { + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + if (instanceRepository.countTable(instanceTable) > 0) { + log.warn("创建表空间{}失败", instanceTable); + return new GeneralResult<>(false, "创建失败"); + } + instanceRepository.createTable(instanceTable, new Instance()); + instanceValueService.createTable(moduleCode, userId); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("create module instance table error:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + public GeneralResult dropTable(String moduleCode, Long userId) { + try { + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + if (instanceRepository.countTable(instanceTable) == 0) { + log.warn("删除表空间{}失败", instanceTable); + return new GeneralResult<>(false, "删除失败"); + } + instanceRepository.dropTable(instanceTable); + instanceValueService.dropTable(moduleCode, userId); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("drop module instance table error:", e); + return new GeneralResult<>(false, "删除失败"); + } + } + + @Override + public GeneralResult list(Pager pager, Long userId) { + try { + List> list = new ArrayList<>(); + if (CollectionUtils.isEmpty(pager.getParams())) { + GridBean> bean = new GridBean<>(pager.getPage(), pager.getRows(), 0, list); + return new GeneralResult<>(true, bean, "查询成功"); + } + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + pager.getSorter().put("id", Common.ONE); + // 模型 + Long moduleId = null; + String moduleCode = ""; + // 实例属性条件查询 + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + Map newMap = new HashMap<>(); + for (String key : paramMap.keySet()) { + if ("moduleCode".equals(key)) { + if (!StringUtils.isEmpty(paramMap.get(key).toString())) { + moduleCode = paramMap.get(key).toString(); + } + } else if ("moduleId".equals(key)) { + if (!StringUtils.isEmpty(paramMap.get(key).toString())) { + moduleId = Long.valueOf(paramMap.get(key).toString()); + } + newMap.put(key, paramMap.get(key)); + } else { + // 将大写字母转化为小写(moduleCode和moduleId之外的参数均为模型属性code参数) + newMap.put(key.toLowerCase(), paramMap.get(key)); + } + } + param.setParam(newMap); + } + if (StringUtils.isEmpty(moduleCode)) { + CiModule modle = moduleRepository.query(moduleId); + if (null == modle) { + return new GeneralResult<>(false, "模型不存在"); + } + + moduleCode = modle.getCode(); + + } + + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + boolean hasAdminRole = checkAdminRole(userId); + int total = instanceRepository.count(pager.getParams(), table, valueTable, userId, hasAdminRole); + list = this.instanceRepository.list(pager, table, valueTable, userId, hasAdminRole); + convertInstanceValue(list, moduleId, userId, hasAdminRole); + GridBean> bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("instance and value list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult create(JSONObject object, Long userId, boolean isAutoRelation) { + try { + // 填充默认值、实例预校验(检验实例的属性值是否满足规则,包括是否必填,最大值、最小值、规则表达式、唯一性等 如果必填,需要补充默认值) + GeneralResult initResult = initInstance(object, InstanceEnum.category.CREATE.name()); + if (initResult.isFailed()) { + log.error("实例预校验失败{}", initResult.getMessage()); + return initResult; + } + Instance instance = (Instance) initResult.getData(); + String table = CmdbUtils.CMDB_INSTANCE + instance.getModuleCode().toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + instance.getModuleCode().toLowerCase(); + Instance cmdbInstance = instanceRepository.queryByUuid(table, instance.getUuid(), instance.getModuleId()); + if (null != cmdbInstance) { + return new GeneralResult<>(false, "实例唯一标识已存在"); + } + instance.setDeleted(false); + instance.setCreatorId(userId); + instance.setGmtCreate(new Date()); + handler.saveInstance(instance, table); + + List instanceValues = instance.getInstanceValues(); + // 实例值记录中查询出实例名称 + List propertyList = queryModulePropertys(instance.getModuleId()); + Map propertyMap = new HashMap<>(); + propertyList.forEach(item -> { + propertyMap.put(item.getCode(), item.getName()); + }); + + instanceValues.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + String instanceName = null; + if (CollectionUtils.isNotEmpty(instanceValues)) { + for (InstanceValue instanceValue : instanceValues) { + // 处理属性默认类型为自增ID及流水号的属性值 + Property property = instanceValue.getProperty(); + if (null != property) { + // 初始化时只保留了前缀 + String propertyValue = instanceValue.getPropertyValue(); + String defaultValueType = property.getDefaultValueType(); + Integer startNum = property.getStartNum(); + if (null == startNum) { + startNum = 0; + } + // 计算后面部分的数值,采用当前实例ID加上开始数值 + Long endNum = instance.getId() + startNum.longValue(); + if (StringUtils.isNotEmpty(defaultValueType) && !"null".equalsIgnoreCase(defaultValueType)) { + if (PropertyConstant.DefaultValueType.SERIALNUM.equalsIgnoreCase(defaultValueType)) { + String value = propertyValue + endNum; + // defaultValue是设置的流水号长度 + String defaultValue = property.getDefaultValue(); + if (StringUtils.isEmpty(defaultValue) || "null".equalsIgnoreCase(defaultValue)) { + defaultValue = "1"; + } + // 如果当前属性值大于流水号长度则删除已经生成的实例 + if (value.length() > Integer.valueOf(defaultValue)) { + instanceRepository.deleteById(instance.getId(), table); + return new GeneralResult<>(false, "实例新增失败:属性" + property.getName() + "内容超过流水号长度"); + } + String valueMiddle = ""; + Integer remainderLength; + remainderLength = Integer.valueOf(defaultValue) - value.length(); + if (remainderLength > 0) { + for (int i = 0; i < remainderLength; i++) { + valueMiddle += "0"; + } + } + propertyValue = propertyValue + valueMiddle + endNum; + } else if (PropertyConstant.DefaultValueType.AUTOINCRID + .equalsIgnoreCase(defaultValueType)) { + propertyValue = propertyValue + endNum; + } + instanceValue.setPropertyValue(propertyValue); + } + } + if (Common.NAME.equals(instanceValue.getPropertyCode())) { + instanceName = instanceValue.getPropertyValue(); + } + instanceValue.setDeleted(false); + instanceValue.setCreatorId(userId); + instanceValue.setGmtCreate(new Date()); + instanceValue.setInstanceId(instance.getId()); + } + handler.batchSaveInstanceValue(instanceValues, valueTable); + } + // 变更记录 + instanceHistoryHelper.history(instance, InstanceEnum.catalog.INSTANCE.name(), + InstanceEnum.category.CREATE.name(), userId); + // 操作审计 + Map afterMap = + JSON.parseObject(JSON.toJSONString(instance), new TypeReference>() { + }); + OperationalAudit cmdbOperationalAudit = operationalAuditService.buildLog(OperationalAuditType.ADD, "实例", + instanceName, instance.getModuleCode(), instance.getId(), userId, null, afterMap); + operationalAuditRepository.save(cmdbOperationalAudit); + if (isAutoRelation) { + // 触发与已有实例之间绑定关系的任务 + instanceAutoRelationService.instanceAutoRelation(instance, userId); + } + + return new GeneralResult<>(true, instance, "实例新增成功"); + } catch (Exception e) { + log.error("instance and value create fail:", e); + return new GeneralResult<>(false, "实例新增失败"); + } + } + + @Override + public GeneralResult batchRemove(InstanceBean model, Long userId) { + try { + String moduleCode = model.getModuleCode(); + CiModule module = moduleRepository.queryByCode(moduleCode); + if (null == module) { + return new GeneralResult<>(false, "模型不存在"); + } + Long moduleId = module.getId(); + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + List instances = instanceRepository.queryList(table, model.getIds()); + if (CollectionUtils.isEmpty(instances)) { + return new GeneralResult<>(false, "实例不存在"); + } + GeneralResult checkRuslt = batchRemoveCheck(model.getIds(), moduleId); + if (checkRuslt.isFailed()) { + return new GeneralResult<>(false, "存在被采集任务使用的实例,不可删除!"); + } + Map instanceMap = instances.stream() + .collect(Collectors.toMap(Instance::getId, Function.identity(), (oldData, newData) -> newData)); + boolean hasAdminRole = checkAdminRole(userId); + + // 先校验当前用户是否拥有删除权限,存在没权限直接跳过 + List instanceIds = new ArrayList<>(); + List instanceList = new ArrayList<>(); + if (!hasAdminRole) { + List instanceAuthoritys = instanceAuthorityRepository.queryByAuth(moduleId, + model.getIds(), userId, InstanceEnum.authority.DEL.name()); + Map authorityMap = instanceAuthoritys.stream().collect(Collectors + .toMap(InstanceAuthority::getInstanceId, Function.identity(), (oldData, newData) -> newData)); + + for (Long id : instanceMap.keySet()) { + Instance temp = instanceMap.get(id); + if (userId.equals(temp.getCreatorId())) { + instanceIds.add(id); + instanceList.add(temp); + continue; + } + InstanceAuthority authority = authorityMap.get(id); + if (null != authority) { + instanceIds.add(id); + instanceList.add(temp); + } + } + + } else { + instanceIds = model.getIds(); + instanceList = instances; + } + + if (CollectionUtils.isEmpty(instanceIds)) { + return new GeneralResult<>(false, "可操作的实例不存在"); + } + + // 审计日志记录,在删除前查询实例value信息 + List values = instanceValueRepository.queryByInstanceIds(valueTable, instanceIds); + instanceValueRepository.batchRemoveByInstanceIds(instanceIds, valueTable, userId); + instanceRepository.batchRemove(instanceIds, table, userId); + instanceAuthorityRepository.batchRemove(moduleId, instanceIds, userId); + instanceHistoryRepository.batchRemove(moduleId, instanceIds); + // 删除关系 + List relations = moduleRelationRepository.queryByModuleId(moduleId); + for (ModuleRelation relation : relations) { + String relationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + relation.getRelationCategoryCode().toLowerCase(); + instanceRelationRepository.batchRemoveByInstanceIds(instanceIds, moduleId, relationTable, userId); + } + // 实例值记录中查询出实例名称 + List propertyList = queryModulePropertys(moduleId); + Map propertyMap = new HashMap<>(); + propertyList.forEach(item -> { + propertyMap.put(item.getCode(), item.getName()); + }); + + values.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + Map> valueMap = + values.stream().collect(Collectors.groupingBy(InstanceValue::getInstanceId)); + Map valueNameMap = + values.stream().filter(item -> item.getPropertyCode().equals(Common.NAME)).collect( + Collectors.toMap(InstanceValue::getInstanceId, Function.identity(), (oldData, newData) -> newData)); + + // 审计操作 + List audits = new ArrayList<>(); + for (Instance temp : instanceList) { + InstanceValue value = valueNameMap.get(temp.getId()); + if (null != value) { + temp.setInstanceValues(valueMap.get(temp.getId())); + // 操作审计 + Map beforeMap = + JSON.parseObject(JSON.toJSONString(temp), new TypeReference>() { + }); + OperationalAudit audit = operationalAuditService.buildLog(OperationalAuditType.BATCH_DELETE, "实例", + value.getPropertyValue(), moduleCode, temp.getId(), userId, beforeMap, null); + audits.add(audit); + } + + } + if (CollectionUtils.isNotEmpty(audits)) { + operationalAuditRepository.batchSave(audits, 100); + } + + return new GeneralResult<>(true, "实例批量删除成功"); + } catch (Exception e) { + log.error("instance and value batch remove fail:", e); + return new GeneralResult<>(false, "实例批量删除失败"); + } + } + + public GeneralResult removeCheck(Long id, Long moduleId) { + try { + List tasks = collectionTaskRepository.findScriptTaskByModuleId(moduleId); + if (CollectionUtils.isEmpty(tasks)) { + return new GeneralResult<>(true, "校验检查成功"); + } + + for (CollectionTask task : tasks) { + if (StringUtils.isEmpty(String.valueOf(task.getGraph()))) { + break; + } + TaskGraph taskGraph = JSONObject.parseObject(String.valueOf(task.getGraph()), TaskGraph.class); + if (null == taskGraph) { + break; + } + if (StringUtils.isEmpty(taskGraph.getTarget())) { + break; + } + JSONObject target = JSONObject.parseObject(taskGraph.getTarget()); + if (null == target) { + break; + } + if (CollectionUtils.isEmpty(target.getJSONArray("data"))) { + break; + } + List data = target.getJSONArray("data").toJavaList(JSONObject.class); + for (JSONObject targetData : data) { + Long instanceId = targetData.getLong("id"); + if (instanceId != null && id.equals(instanceId)) { + return new GeneralResult<>(false, "校验检查失败"); + } + } + } + return new GeneralResult<>(true, "校验检查成功"); + } catch (Exception e) { + log.error("instance remove check fail:", e); + return new GeneralResult<>(false, "校验检查失败"); + } + } + + public GeneralResult batchRemoveCheck(List ids, Long moduleId) { + try { + List tasks = collectionTaskRepository.findScriptTaskByModuleId(moduleId); + if (CollectionUtils.isEmpty(tasks)) { + return new GeneralResult<>(true, "校验检查成功"); + } + + for (CollectionTask task : tasks) { + if (StringUtils.isEmpty(String.valueOf(task.getGraph()))) { + break; + } + TaskGraph taskGraph = JSONObject.parseObject(String.valueOf(task.getGraph()), TaskGraph.class); + if (null == taskGraph) { + break; + } + if (StringUtils.isEmpty(taskGraph.getTarget())) { + break; + } + JSONObject target = JSONObject.parseObject(taskGraph.getTarget()); + if (null == target) { + break; + } + if (CollectionUtils.isEmpty(target.getJSONArray("data"))) { + break; + } + List data = target.getJSONArray("data").toJavaList(JSONObject.class); + for (JSONObject targetData : data) { + Long instanceId = targetData.getLong("id"); + if (instanceId != null && ids.contains(instanceId)) { + return new GeneralResult<>(false, "校验检查失败"); + } + } + } + return new GeneralResult<>(true, "校验检查成功"); + } catch (Exception e) { + log.error("instance remove check fail:", e); + return new GeneralResult<>(false, "校验检查失败"); + } + } + + @Override + public GeneralResult remove(Long id, String moduleCode, Long userId) { + String path = Instance.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + CiModule module = moduleRepository.queryByCode(moduleCode); + if (null == module) { + return new GeneralResult<>(false, "模型不存在"); + } + Long moduleId = module.getId(); + Instance temp = instanceRepository.query(table, id); + if (null == temp) { + return new GeneralResult<>(false, "实例不存在"); + } + GeneralResult checkRuslt = removeCheck(id, moduleId); + if (checkRuslt.isFailed()) { + return new GeneralResult<>(false, "该实例已被采集任务使用,不可删除!"); + } + boolean hasAdminRole = checkAdminRole(userId); + if (!hasAdminRole && !temp.getCreatorId().equals(userId)) { + InstanceAuthority authority = + instanceAuthorityRepository.queryByAuth(moduleId, id, userId, InstanceEnum.authority.DEL.name()); + if (null == authority) { + return new GeneralResult<>(false, "实例无删除权限"); + } + } + List instanceValues = instanceValueRepository.listByInstanceId(id, valueTable); + // 实例值记录中查询出实例名称 + List propertyList = queryModulePropertys(temp.getModuleId()); + Map propertyMap = new HashMap<>(); + propertyList.forEach(item -> { + propertyMap.put(item.getCode(), item.getName()); + }); + + instanceValues.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + temp.setInstanceValues(instanceValues); + InstanceValue valueTemp = instanceValueRepository.query(valueTable, Common.NAME, id); + if (null == valueTemp) { + return new GeneralResult<>(false, "实例不存在"); + } + instanceValueRepository.removeByInstanceId(id, valueTable, userId); + instanceRepository.remove(id, table, userId); + instanceAuthorityRepository.remove(moduleId, id, userId); + instanceHistoryRepository.remove(moduleId, id); + // 删除关系 + List relations = moduleRelationRepository.queryByModuleId(moduleId); + for (ModuleRelation relation : relations) { + String relationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + relation.getRelationCategoryCode().toLowerCase(); + instanceRelationRepository.removeByInstanceId(id, moduleId, relationTable, userId); + } + // 操作审计 + Map beforeMap = + JSON.parseObject(JSON.toJSONString(temp), new TypeReference>() { + }); + OperationalAudit audit = operationalAuditService.buildLog(OperationalAuditType.DELETE, "实例", + valueTemp.getPropertyValue(), moduleCode, temp.getId(), userId, beforeMap, null); + operationalAuditRepository.save(audit); + return new GeneralResult<>(true, "实例删除成功"); + } catch (Exception e) { + log.error("instance and value remove fail:", e); + return new GeneralResult<>(false, "实例删除失败"); + } + } + + @Override + public GeneralResult batchModify(InstanceBean instanceModel, Long userId) { + try { + Long moduleId = instanceModel.getModuleId(); + String moduleCode = instanceModel.getModuleCode(); + String propertyCode = instanceModel.getPropertyCode(); + Object propertyValue = instanceModel.getPropertyValue(); + if (CollectionUtils.isEmpty(instanceModel.getIds())) { + return new GeneralResult<>(false, "实例不存在"); + } + boolean hasAdminRole = checkAdminRole(userId); + CiModule module = moduleRepository.query(moduleId); + if (null == module || !module.getCode().equals(moduleCode)) { + return new GeneralResult<>(false, "模型不存在"); + } + + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + + List instances = instanceRepository.queryList(instanceTable, instanceModel.getIds()); + if (CollectionUtils.isEmpty(instances)) { + return new GeneralResult<>(false, "实例不存在"); + } + Map instanceMap = instances.stream() + .collect(Collectors.toMap(Instance::getId, Function.identity(), (oldData, newData) -> newData)); + + // 先校验当前用户是否拥有修改的权限,存在没权限直接跳过 + List instanceIds = new ArrayList<>(); + List instanceList = new ArrayList<>(); + if (!hasAdminRole) { + List instanceAuthoritys = instanceAuthorityRepository.queryByAuth(moduleId, + instanceModel.getIds(), userId, InstanceEnum.authority.EDIT.name()); + Map authorityMap = instanceAuthoritys.stream().collect(Collectors + .toMap(InstanceAuthority::getInstanceId, Function.identity(), (oldData, newData) -> newData)); + + for (Long id : instanceMap.keySet()) { + Instance temp = instanceMap.get(id); + if (userId.equals(temp.getCreatorId())) { + instanceIds.add(id); + instanceList.add(temp); + continue; + } + InstanceAuthority authority = authorityMap.get(id); + if (null != authority) { + instanceIds.add(id); + instanceList.add(temp); + } + } + + } else { + instanceIds = instanceModel.getIds(); + instanceList = instances; + } + + if (CollectionUtils.isEmpty(instanceIds)) { + return new GeneralResult<>(false, "可操作的实例不存在"); + } + + Property property = propertyRepository.queryByCode(moduleId, propertyCode); + if (null == property) { + return new GeneralResult<>(false, "模型属性不存在"); + } + String propertyType = property.getType(); + // 清空数据 + if (InstanceEnum.type.CLEAN_DATA.name().equalsIgnoreCase(instanceModel.getType())) { + propertyValue = ""; + } + // 验证修改值是否满足属性约束 + boolean validateResult = validate(property, moduleCode, propertyValue); + if (!validateResult) { + return new GeneralResult<>(false, "属性值不符合属性约束"); + } + + List values = instanceValueRepository.queryByInstanceIds(instanceValueTable, instanceIds); + // 实例值记录中查询出实例名称 + List propertyList = queryModulePropertys(moduleId); + Map propertyMap = new HashMap<>(); + propertyList.forEach(item -> { + propertyMap.put(item.getCode(), item.getName()); + }); + + values.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + + Map> valueMap = + values.stream().collect(Collectors.groupingBy(InstanceValue::getInstanceId)); + + Map valueNameMap = + values.stream().filter(item -> item.getPropertyCode().equals(Common.NAME)).collect( + Collectors.toMap(InstanceValue::getInstanceId, Function.identity(), (oldData, newData) -> newData)); + Map propertyValueMap = + values.stream().filter(item -> item.getPropertyCode().equals(propertyCode)).collect( + Collectors.toMap(InstanceValue::getInstanceId, Function.identity(), (oldData, newData) -> newData)); + + List updateInstanceValueList = new ArrayList<>(); + List addInstanceValueList = new ArrayList<>(); + List updateInstanceList = new ArrayList<>(); + + Map> oldMap = new HashMap<>(); + for (Instance instance : instanceList) { + InstanceValue nameValue = valueNameMap.get(instance.getId()); + if (null == nameValue) { + log.error("实例值不存在", instance); + continue; + } + InstanceValue instanceValue = propertyValueMap.get(instance.getId()); + String propertyValueStr = String.valueOf(propertyValue); + if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.JSON.equals(propertyType) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + propertyValueStr = JSON.toJSONString(propertyValue); + } + instance.setInstanceValues(valueMap.get(instance.getId())); + Map beforeMap = + JSON.parseObject(JSON.toJSONString(instance), new TypeReference>() { + }); + oldMap.put(instance.getId(), beforeMap); + if (null == instanceValue) { + // 新增属性 + instanceValue = new InstanceValue(); + instanceValue.setInstanceId(instance.getId()); + instanceValue.setPropertyId(property.getId()); + instanceValue.setPropertyCode(property.getCode()); + instanceValue.setPropertyValue(propertyValueStr); + instanceValue.setCreatorId(userId); + instanceValue.setGmtCreate(new Date()); + addInstanceValueList.add(instanceValue); + } else { + instanceValue.setPropertyValue(propertyValueStr); + instanceValue.setMenderId(userId); + instanceValue.setGmtModify(new Date()); + updateInstanceValueList.add(instanceValue); + } + instance.setMenderId(userId); + instance.setGmtModify(new Date()); + updateInstanceList.add(instance); + + } + if (CollectionUtils.isNotEmpty(updateInstanceList)) { + handler.batchUpdateInstance(updateInstanceList, instanceTable); + //更新实例关系数据 + for (Instance instance : updateInstanceList) { + List categories = relationCategoryRepository.list(Lists.newArrayList(), Maps.newHashMap()); + for (RelationCategory category : categories) { + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + category.getCode().toLowerCase(); + instanceRelationRepository.updateOfnameBySourceId(instance.getName(), relationTable, instance.getId(), userId); + instanceRelationRepository.updateOfnameByTargetId(instance.getName(), relationTable, instance.getId(), userId); + } + } + } + if (CollectionUtils.isNotEmpty(updateInstanceValueList)) { + handler.batchUpdateInstanceValue(updateInstanceValueList, instanceValueTable); + } + if (CollectionUtils.isNotEmpty(addInstanceValueList)) { + handler.batchSaveInstanceValue(addInstanceValueList, instanceValueTable); + } + + // 实例操作记录 + List instanceHistoryList = new ArrayList<>(); + // 审计操作 + List newValues = instanceValueRepository.queryByInstanceIds(instanceValueTable, instanceIds); + newValues.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + Map> newValueMap = + newValues.stream().collect(Collectors.groupingBy(InstanceValue::getInstanceId)); + List audits = new ArrayList<>(); + for (Instance instance : instanceList) { + InstanceValue nameValue = valueNameMap.get(instance.getId()); + if (null == nameValue) { + log.error("实例值不存在", instance); + continue; + } + instance.setInstanceValues(newValueMap.get(instance.getId())); + InstanceHistory history = instanceHistoryHelper.getInstanceHistory(instance, module, nameValue, + InstanceEnum.catalog.INSTANCE.name(), InstanceEnum.category.BATCH_MODIFY.name(), userId); + if (null != history) { + instanceHistoryList.add(history); + } + + Map beforeMap = oldMap.get(instance.getId()); + Map afterMap = + JSON.parseObject(JSON.toJSONString(instance), new TypeReference>() { + }); + OperationalAudit audit = operationalAuditService.buildLog(OperationalAuditType.BATCH_MODIFY, "实例", + nameValue.getPropertyValue(), moduleCode, instance.getId(), userId, beforeMap, afterMap); + audits.add(audit); + } + if (CollectionUtils.isNotEmpty(audits)) { + operationalAuditRepository.batchSave(audits, 100); + } + + if (CollectionUtils.isNotEmpty(instanceHistoryList)) { + instanceHistoryRepository.batchSave(instanceHistoryList, 100); + } + + return new GeneralResult<>(true, "实例批量编辑成功"); + } catch (Exception e) { + log.error("instance and value batch modify fail:", e); + return new GeneralResult<>(false, "实例批量编辑失败"); + } + } + + @Override + public GeneralResult modify(JSONObject object, Long userId) { + // 模型判断及实例属性值校验 + GeneralResult initResult = initInstance(object, InstanceEnum.category.MODIFY.name()); + if (initResult.isFailed()) { + log.error("实例预校验失败{}", initResult.getMessage()); + return initResult; + } + Instance instance = (Instance) initResult.getData(); + String path = Instance.class.getSimpleName() + "_" + instance.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + String table = CmdbUtils.CMDB_INSTANCE + instance.getModuleCode().toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + instance.getModuleCode().toLowerCase(); + Instance temp = instanceRepository.query(table, instance.getId()); + Instance oldInstance = new Instance(); + BeanUtils.copyProperties(temp, oldInstance); + if (null == temp) { + return new GeneralResult<>(false, "实例不存在"); + } + temp.setName(object.getString("name")); + boolean hasAdminRole = checkAdminRole(userId); + if (!hasAdminRole && !temp.getCreatorId().equals(userId)) { + InstanceAuthority authority = instanceAuthorityRepository.queryByAuth(instance.getModuleId(), + instance.getId(), userId, InstanceEnum.authority.EDIT.name()); + if (null == authority) { + return new GeneralResult<>(false, "实例无编辑权限"); + } + } + InstanceValue nameValue = instanceValueRepository.query(valueTable, Common.NAME, instance.getId()); + if (null == nameValue) { + return new GeneralResult<>(false, "实例不存在"); + } + // 实例值记录中查询出实例名称 + List propertyList = queryModulePropertys(instance.getModuleId()); + Map propertyMap = new HashMap<>(); + propertyList.forEach(item -> { + propertyMap.put(item.getCode(), item.getName()); + }); + + List oldValues = instanceValueRepository.listByInstanceId(instance.getId(), valueTable); + oldValues.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + temp.setInstanceValues(oldValues); + Map beforeMap = + JSON.parseObject(JSON.toJSONString(temp), new TypeReference>() { + }); + temp.setGmtModify(new Date()); + temp.setMenderId(userId); + handler.updateInstance(temp, table); + //更新实例关系数据 + List categories = relationCategoryRepository.list(Lists.newArrayList(), Maps.newHashMap()); + for (RelationCategory category : categories) { + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + category.getCode().toLowerCase(); + instanceRelationRepository.updateOfnameBySourceId(temp.getName(), relationTable, temp.getId(), userId); + instanceRelationRepository.updateOfnameByTargetId(temp.getName(), relationTable, temp.getId(), userId); + } + List instanceValues = instance.getInstanceValues(); + // 不存在即新增 + if (CollectionUtils.isEmpty(oldValues)) { + if (CollectionUtils.isNotEmpty(instanceValues)) { + for (InstanceValue instanceValue : instanceValues) { + instanceValue.setDeleted(false); + instanceValue.setCreatorId(userId); + instanceValue.setGmtCreate(new Date()); + instanceValue.setInstanceId(instance.getId()); + Property property = instanceValue.getProperty(); + if (null == property) { + continue; + } + // 初始化时只保留了前缀 + String defaultValueType = property.getDefaultValueType(); + if (StringUtils.isNotEmpty(defaultValueType) && !"null".equalsIgnoreCase(defaultValueType)) { + String propertyValue = instanceValue.getPropertyValue(); + Integer startNum = property.getStartNum(); + if (null == startNum) { + startNum = 0; + } + // 计算后面部分的数值 + Long endNum = instance.getId() + startNum.longValue(); + if (PropertyConstant.DefaultValueType.SERIALNUM.equalsIgnoreCase(defaultValueType)) { + String value = propertyValue + endNum; + // defaultValue是设置的流水号长度 + String defaultValue = property.getDefaultValue(); + if (StringUtils.isEmpty(defaultValue) || "null".equalsIgnoreCase(defaultValue)) { + defaultValue = "1"; + } + // 如果当前属性值大于流水号长度则删除已经生成的实例 + if (value.length() > Integer.valueOf(defaultValue)) { + handler.updateInstance(oldInstance, table); + return new GeneralResult<>(false, "实例更新失败:属性" + property.getName() + "内容超过流水号长度"); + } + String valueMiddle = ""; + Integer remainderLength; + remainderLength = Integer.valueOf(defaultValue) - value.length(); + if (remainderLength > 0) { + for (int i = 0; i < remainderLength; i++) { + valueMiddle += "0"; + } + } + propertyValue = propertyValue + valueMiddle + endNum; + } else if (PropertyConstant.DefaultValueType.AUTOINCRID + .equalsIgnoreCase(defaultValueType)) { + propertyValue = propertyValue + endNum; + } else if (PropertyConstant.DefaultValueType.INNERFUN.equalsIgnoreCase(defaultValueType)) { + propertyValue = IDFactory.instance().uuid(); + } + instanceValue.setPropertyValue(propertyValue); + } + } + handler.batchSaveInstanceValue(instanceValues, valueTable); + } + } else { + if (CollectionUtils.isNotEmpty(instanceValues)) { + List addList = new ArrayList<>(); + List updateList = new ArrayList<>(); + Map> instanceValueMap = + oldValues.stream().collect(Collectors.groupingBy(InstanceValue::getId)); + for (InstanceValue instanceValue : instanceValues) { + if (null == instanceValue.getId() || 0L == instanceValue.getId()) { + instanceValue.setDeleted(false); + instanceValue.setCreatorId(userId); + instanceValue.setGmtCreate(new Date()); + instanceValue.setInstanceId(instance.getId()); + // 判断类型 + Property property = instanceValue.getProperty(); + if (null != property) { + // 初始化时只保留了前缀 + String defaultValueType = property.getDefaultValueType(); + if (StringUtils.isNotEmpty(defaultValueType) + && !"null".equalsIgnoreCase(defaultValueType)) { + String propertyValue = instanceValue.getPropertyValue(); + Integer startNum = property.getStartNum(); + if (null == startNum) { + startNum = 0; + } + // 计算后面部分的数值 + Long endNum = instance.getId() + startNum.longValue(); + if (PropertyConstant.DefaultValueType.SERIALNUM + .equalsIgnoreCase(defaultValueType)) { + String value = propertyValue + endNum; + // defaultValue是设置的流水号长度 + String defaultValue = property.getDefaultValue(); + if (StringUtils.isEmpty(defaultValue) + || "null".equalsIgnoreCase(defaultValue)) { + defaultValue = "1"; + } + // 如果当前属性值大于流水号长度则删除已经生成的实例 + if (value.length() > Integer.valueOf(defaultValue)) { + handler.updateInstance(oldInstance, table); + return new GeneralResult<>(false, + "实例更新失败:属性" + property.getName() + "内容超过流水号长度"); + } + String valueMiddle = ""; + Integer remainderLength; + remainderLength = Integer.valueOf(defaultValue) - value.length(); + if (remainderLength > 0) { + for (int i = 0; i < remainderLength; i++) { + valueMiddle += "0"; + } + } + propertyValue = propertyValue + valueMiddle + endNum; + } else if (PropertyConstant.DefaultValueType.AUTOINCRID + .equalsIgnoreCase(defaultValueType)) { + propertyValue = propertyValue + endNum; + } else if (PropertyConstant.DefaultValueType.INNERFUN + .equalsIgnoreCase(defaultValueType)) { + propertyValue = IDFactory.instance().uuid(); + } + instanceValue.setPropertyValue(propertyValue); + } + } + addList.add(instanceValue); + } else { + instanceValue.setMenderId(userId); + instanceValue.setGmtModify(new Date()); + updateList.add(instanceValue); + instanceValueMap.remove(instanceValue.getId()); + } + } + if (CollectionUtils.isNotEmpty(addList)) { + handler.batchSaveInstanceValue(addList, valueTable); + } + if (CollectionUtils.isNotEmpty(updateList)) { + handler.batchUpdateInstanceValue(updateList, valueTable); + } + instanceValueMap.clear(); + } + } + instanceHistoryHelper.history(instance, InstanceEnum.catalog.INSTANCE.name(), + InstanceEnum.category.MODIFY.name(), userId); + // 操作审计 + instanceValues = instanceValueRepository.listByInstanceId(instance.getId(), valueTable); + instanceValues.forEach(item -> { + item.setName(propertyMap.get(item.getPropertyCode())); + }); + temp.setInstanceValues(instanceValues); + Map afterMap = + JSON.parseObject(JSON.toJSONString(temp), new TypeReference>() { + }); + OperationalAudit audit = operationalAuditService.buildLog(OperationalAuditType.MODIFY, "实例", + nameValue.getPropertyValue(), instance.getModuleCode(), instance.getId(), userId, beforeMap, afterMap); + operationalAuditRepository.save(audit); + return new GeneralResult<>(true, temp, "实例修改成功"); + } catch (Exception e) { + log.error("instance and value modify fail:", e); + return new GeneralResult<>(false, "实例修改失败"); + } + } + + @Override + public GeneralResult detail(Long id, String moduleCode) { + try { + String table = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + Instance instance = instanceRepository.query(table, id); + List values = instanceValueRepository.listByInstanceId(id, valueTable); + // instance.setInstanceObject(CmdbUtils.instanceValueRowToCol(instanceValues)); + // convertInstanceValue(instance.getInstanceObject(), instance.getModuleId()); + instance.setInstanceValues(values); + return new GeneralResult<>(true, instance, "实例详情查询成功"); + } catch (Exception e) { + log.error("instance and value detail fail:", e); + return new GeneralResult<>(false, "实例详情查询失败"); + } + } + + @Override + public GeneralResult export(Long moduleId, String moduleCode, String type, Long userId) { + Workbook workbook = null; + try { + boolean hasAdminRole = checkAdminRole(userId); + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return new GeneralResult<>(false, "模型数据不存在"); + } + if (!moduleCode.equals(module.getCode())) { + return new GeneralResult<>(false, "模型数据不存在"); + } + String table = CmdbUtils.CMDB_INSTANCE + module.getCode().toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + List> instances = + instanceRepository.listAll(table, valueTable, module.getId(), null, userId, hasAdminRole); + List properties = queryModulePropertys(module.getId()); + String fileName = module.getName() + "-实例.xls"; + if ("2007".equals(type)) { + fileName = fileName + "x"; + } + workbook = new ExcelFactory(fileName).newWorkbook(); + // 构建表头 + excelHelper.generateSheet(workbook, module, properties); + // 构建数据 + excelHelper.generateDate(workbook, properties, instances); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + workbook.write(baos); + byte[] ba = baos.toByteArray(); + Map resultMap = Maps.newHashMap(); + resultMap.put("fileName", fileName); + resultMap.put("data", Base64.getEncoder().encodeToString(ba)); + return new GeneralResult<>(true, resultMap, "导出成功"); + } catch (Exception e) { + log.error("instance data export fail:", e); + return new GeneralResult<>(false, "导出失败"); + } + } + + /*** + * 填充默认值、实例预校验(检验实例的属性值是否满足规则,包括是否必填,最大值、最小值、规则表达式、唯一性等 如果必填,需要补充默认值) + * + * @param object + * @param type + * @return + */ + @Override + public GeneralResult initInstance(JSONObject object, String type) { + try { + StringBuilder message = new StringBuilder(); + // 将数据循环转换 + Map objectMap = new HashMap<>(); + for (Map.Entry entry : object.entrySet()) { + objectMap.put(entry.getKey(), entry.getValue()); + } + // 校验模型是否存在 + Long moduleId = object.getLong("moduleId"); + String moduleCode = object.getString("moduleCode"); + CiModule module = moduleRepository.query(moduleId); + if (null == module + || (StringUtils.isNotEmpty(moduleCode) && !moduleCode.equalsIgnoreCase(module.getCode()))) { + log.error("预检失败,模型{}不存在", moduleCode); + message.append(moduleCode + "模型不存在\n"); + return new GeneralResult<>(false, "模型不存在"); + } + // 处理数据 + Instance instance = new Instance(); + instance.setModuleId(moduleId); + instance.setModuleCode(moduleCode); + // 当页面传递参数为空时,填充默认值 + String uuid = IDFactory.instance().uuid(); + if (InstanceEnum.category.CREATE.name().equalsIgnoreCase(type)) { + instance.setUuid(uuid); + instance.setName(object.getString("name")); + } + // 校验模型属性是否存在 + List properties = queryModulePropertys(module.getId()); + if (CollectionUtils.isEmpty(properties)) { + log.error("预检失败,模型属性不存在"); + message.append(moduleCode + "模型属性不存在\n"); + return new GeneralResult<>(false, "模型属性不存在"); + } + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getCode(), property); + } + List instanceValues = new ArrayList<>(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + // 数据转换 + if (InstanceEnum.category.MODIFY.name().equalsIgnoreCase(type)) { + instance.setId(object.getLong(Common.ID)); + List oldValues = instanceValueRepository.listByInstanceId(instance.getId(), valueTable); + Iterator iterator = oldValues.iterator(); + while (iterator.hasNext()) { + InstanceValue oldInstanceValue = iterator.next(); + Property property = propertyMap.get(oldInstanceValue.getPropertyCode()); + if (null == property) { + continue; + } + if (!oldInstanceValue.getPropertyId().equals(property.getId())) { + continue; + } + String propertyType = property.getType(); + Boolean propertyOnlyReader = property.getIsOnlyReader(); + // 存在即替换值 + if (objectMap.containsKey(oldInstanceValue.getPropertyCode())) { + InstanceValue instanceValue = oldInstanceValue; + // 只读不做编辑 + if ((null == propertyOnlyReader || !propertyOnlyReader)) { + if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.JSON.equals(propertyType) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + instanceValue.setPropertyValue( + JSON.toJSONString(objectMap.get(oldInstanceValue.getPropertyCode()))); + } else { + if (null != objectMap.get(oldInstanceValue.getPropertyCode())) { + instanceValue.setPropertyValue( + String.valueOf(objectMap.get(oldInstanceValue.getPropertyCode()))); + } + } + } + instanceValues.add(instanceValue); + objectMap.remove(oldInstanceValue.getPropertyCode()); + } + } + // 剩余的为新增属性及数据 + if (objectMap.size() > 0) { + for (Map.Entry entry : objectMap.entrySet()) { + InstanceValue instanceValue = new InstanceValue(); + Property property = propertyMap.get(entry.getKey()); + // 剔除不存在的属性 + if (null == property) { + continue; + } + String propertyType = property.getType(); + instanceValue.setPropertyId(property.getId()); + instanceValue.setPropertyCode(entry.getKey()); + if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.JSON.equals(propertyType) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + instanceValue.setPropertyValue(JSON.toJSONString(entry.getValue())); + } else { + if (null != entry.getValue()) { + instanceValue.setPropertyValue(String.valueOf(entry.getValue())); + } + } + instanceValues.add(instanceValue); + } + } + } else if (InstanceEnum.category.CREATE.name().equalsIgnoreCase(type)) { + for (Map.Entry entry : objectMap.entrySet()) { + InstanceValue instanceValue = new InstanceValue(); + Property property = propertyMap.get(entry.getKey()); + // 剔除不存在的属性 + if (null == property) { + continue; + } + String propertyType = property.getType(); + instanceValue.setPropertyId(property.getId()); + instanceValue.setPropertyCode(entry.getKey()); + if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.JSON.equals(propertyType) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + instanceValue.setPropertyValue(JSON.toJSONString(entry.getValue())); + } else { + if (null != entry.getValue()) { + instanceValue.setPropertyValue(String.valueOf(entry.getValue())); + } + } + instanceValues.add(instanceValue); + } + } + instance.setInstanceValues(instanceValues); + // 检查数据值 + Iterator iterator = instanceValues.iterator(); + // 检验实例的属性值是否满足规则,包括是否必填,最大值、最小值、规则表达式、唯一性等 + // 如果必填,需要补充默认值 + while (iterator.hasNext()) { + InstanceValue instanceValue = iterator.next(); + // 当前实例属性值 + Long propertyId = instanceValue.getPropertyId(); + String propertyValue = instanceValue.getPropertyValue(); + String propertyCode = instanceValue.getPropertyCode(); + Property property = propertyMap.get(propertyCode); + if (null == property) { + iterator.remove(); + continue; + } + String propertyName = property.getName(); + // 是否补充默认值 + if (StringUtils.isEmpty(propertyValue) && StringUtils.isNotEmpty(property.getDefaultValue())) { + instanceValue.setPropertyValue(property.getDefaultValue()); + } + String propertyType = property.getType(); + + // 单行文本中流水号、自增、内置函数不校验数据规则,值代码中自动生成 + String defaultValueType = property.getDefaultValueType(); + if (PropertyConstant.PropertyType.TEXTFIELD.equals(propertyType)) { + if (PropertyConstant.DefaultValueType.SERIALNUM.equalsIgnoreCase(defaultValueType) + || PropertyConstant.DefaultValueType.AUTOINCRID.equalsIgnoreCase(defaultValueType) + || PropertyConstant.DefaultValueType.INNERFUN.equalsIgnoreCase(defaultValueType)) { + propertyMap.remove(propertyCode); + // 存储起来供保存时使用 + instanceValue.setProperty(property); + continue; + } + } + if (!"null".equalsIgnoreCase(propertyValue) && StringUtils.isNotEmpty(propertyValue)) { + // 验证属性项 + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + validatePropertyItem(instance, instanceValue, property, message); + } else if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType)) { + validateArray(instance, instanceValue, property, message); + } else if (PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + // 多行表格 + validateProperty(instance, instanceValue, property, message); + } else if ((PropertyConstant.PropertyType.INTEGER.equals(propertyType) + || PropertyConstant.PropertyType.FLOAT.equals(propertyType))) { + // 验证数值 + validateNumber(instance, instanceValue, property, message); + } else if (PropertyConstant.PropertyType.BOOLEAN.equals(propertyType) + && !CmdbUtils.isBool(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]非布尔类型\n"); + } else if (PropertyConstant.PropertyType.JSON.equals(propertyType)) { + GeneralResult result = JSONTools.isJSON(propertyValue); + if (result.isFailed()) { + JSONArray array = JSONTools.parseStr2JsonArray(propertyValue); + if (null == array) { + message + .append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]非JSON\n"); + } + } + + } else if (PropertyConstant.PropertyType.DATE.equals(propertyType) + && !CmdbUtils.isDate(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]非日期类型\n"); + } else if (PropertyConstant.PropertyType.TIME.equals(propertyType) + && !CmdbUtils.isTime(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]非时间类型\n"); + } else if (PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + // 加密的校验 + if (StringUtils.isNotEmpty(propertyValue)) { + // 密码解密 + Encryptor encryptor = new AESEncryptor(); + String password = encryptor.decrypt(propertyValue, null); + if (null != property.getLength() && property.getLength() > 0 + && StringUtils.isNotEmpty(password) && password.length() > property.getLength()) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]超过限制长度[" + + property.getLength() + "]\n"); + } + } + } + + // 规则表达式 + if (null != property.getRegexpId() + && !PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + RegularExpression expression = regularExpressionRepository.query(property.getRegexpId()); + if (null != expression && StringUtils.isNotEmpty(expression.getExpression())) { + boolean flag = + CmdbUtils.contains(expression.getExpression(), String.valueOf(propertyValue)); + if (!flag) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + + "]不满足属性表达式[" + expression.getExpression() + "]\n"); + } + } + } + } + + // 是否必填 + if (property.getIsRequired() + && (StringUtils.isEmpty(propertyValue) || "null".equalsIgnoreCase(propertyValue))) { + message.append(moduleCode + "实例属性[" + propertyName + "]是必填项\n"); + } + // 是否超过长度限制 + if (!PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType) && null != property.getLength() + && property.getLength() > 0 && StringUtils.isNotEmpty(propertyValue) + && propertyValue.length() > property.getLength()) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]超过限制长度[" + + property.getLength() + "]\n"); + } + // 唯一性 + if (property.getIsUniqued() && StringUtils.isNotEmpty(propertyValue)) { + InstanceValue checkValue = instanceValueRepository.query(valueTable, propertyCode, propertyValue); + if (InstanceEnum.category.CREATE.name().equalsIgnoreCase(type)) { + if (null != checkValue) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]已存在\n"); + } + } else if (InstanceEnum.category.MODIFY.name().equalsIgnoreCase(type)) { + if (null != checkValue && !(checkValue.getInstanceId() + "-" + checkValue.getPropertyCode()) + .equals(instance.getId() + "-" + instanceValue.getPropertyCode())) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]已存在\n"); + } + } + } + propertyMap.remove(propertyCode); + } + // 是否缺少属性 + if (!propertyMap.isEmpty()) { + // 处理属性默认类型,包括内置函数、自增ID、流水号等 + Iterator> it = propertyMap.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + // 设置UUID + if (Common.UUID.equals(entry.getKey()) + && InstanceEnum.category.CREATE.name().equalsIgnoreCase(type)) { + InstanceValue instanceValue = new InstanceValue(); + instanceValue.setPropertyId(entry.getValue().getId()); + instanceValue.setPropertyCode(entry.getValue().getCode()); + instanceValue.setPropertyValue(uuid); + instanceValues.add(instanceValue); + it.remove(); + } else if (Common.UUID.equals(entry.getKey()) + && InstanceEnum.category.MODIFY.name().equalsIgnoreCase(type)) { + // 编辑情况下,UUID不处理 + it.remove(); + } else if (!Common.NAME.equals(entry.getKey()) && (PropertyConstant.DefaultValueType.FIXED + .equalsIgnoreCase(entry.getValue().getDefaultValueType()) + || PropertyConstant.DefaultValueType.INNERFUN + .equalsIgnoreCase(entry.getValue().getDefaultValueType()) + || PropertyConstant.DefaultValueType.AUTOINCRID + .equalsIgnoreCase(entry.getValue().getDefaultValueType()) + || PropertyConstant.DefaultValueType.SERIALNUM + .equalsIgnoreCase(entry.getValue().getDefaultValueType()))) { + // 存在默认类型的需要特殊处理,自增ID、流水号 + InstanceValue instanceValue = new InstanceValue(); + instanceValue.setPropertyId(entry.getValue().getId()); + instanceValue.setPropertyCode(entry.getValue().getCode()); + setDefaultValue(entry.getValue(), instanceValue); + instanceValues.add(instanceValue); + it.remove(); + } + } + for (Property property : propertyMap.values()) { + if (property.getIsRequired()) { + message.append(moduleCode + "对应模型属性[" + property.getName() + "]为必填属性\n"); + } + } + } + if (StringUtils.isNotEmpty(message.toString())) { + return new GeneralResult<>(false, message.toString()); + } + return new GeneralResult<>(true, instance, "实例预检成功"); + } catch (Exception e) { + log.error("CmdbModuleInstance preCheck fail", e); + return new GeneralResult<>(false, "实例预检失败:" + e.getMessage()); + } + } + + /*** + * 设置默认值,只处理新增情况 + * + * @param property + * @param instanceValue + */ + private void setDefaultValue(Property property, InstanceValue instanceValue) { + try { + String propertyValue = instanceValue.getPropertyValue(); + String defaultValueType = property.getDefaultValueType(); + String defaultValue = property.getDefaultValue(); + String prefixIdentifier = property.getPrefixIdentifier(); + if (StringUtils.isNotEmpty(defaultValueType) && !"null".equalsIgnoreCase(defaultValueType)) { + if (StringUtils.isEmpty(propertyValue)) { + if (PropertyConstant.DefaultValueType.FIXED.equalsIgnoreCase(defaultValueType)) { + propertyValue = defaultValue; + } else if (PropertyConstant.DefaultValueType.INNERFUN.equalsIgnoreCase(defaultValueType)) { + // 存储起来供保存时使用 + instanceValue.setProperty(property); + propertyValue = IDFactory.instance().uuid(); + } else if (PropertyConstant.DefaultValueType.SERIALNUM.equalsIgnoreCase(defaultValueType) + || PropertyConstant.DefaultValueType.AUTOINCRID.equalsIgnoreCase(defaultValueType)) { + propertyValue = StringUtils.isNotEmpty(prefixIdentifier) ? prefixIdentifier : ""; + // 存储起来供保存时使用 + instanceValue.setProperty(property); + } + } else { + propertyValue = defaultValue; + } + instanceValue.setPropertyValue(propertyValue); + } + } catch (Exception e) { + log.error("设置默认值失败", e); + } + } + + /*** + * 验证存在子项 + * + * @param instance + * @param instanceValue + * @param property + * @param message + */ + private void validatePropertyItem(Instance instance, InstanceValue instanceValue, Property property, + StringBuilder message) { + String moduleCode = instance.getModuleCode(); + String propertyValue = instanceValue.getPropertyValue(); + String propertyName = property.getName(); + try { + // 判断属性值是否存在 + List propertyItems = property.getItemList(); + if (CollectionUtils.isEmpty(propertyItems)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项不存在\n"); + return; + } + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getValue(), propertyItem); + } + if (!propertyItemMap.containsKey(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项不存在\n"); + } + } catch (Exception e) { + log.error("验证子项失败", e); + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项验证失败\n"); + } + } + + /*** + * 验证复选框及复选下拉框 + * + * @param instance + * @param instanceValue + * @param property + * @param message + */ + private void validateArray(Instance instance, InstanceValue instanceValue, Property property, + StringBuilder message) { + String moduleCode = instance.getModuleCode(); + String propertyValue = instanceValue.getPropertyValue(); + String propertyName = property.getName(); + try { + // 判断属性值是否存在 + List propertyItems = property.getItemList(); + if (CollectionUtils.isEmpty(propertyItems)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项不存在\n"); + return; + } + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getValue(), propertyItem); + } + List values = JSONObject.parseArray(propertyValue, String.class); + for (String value : values) { + if (!propertyItemMap.containsKey(value)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项不存在\n"); + break; + } + } + } catch (Exception e) { + log.error("验证子项失败", e); + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项验证失败\n"); + } + } + + /*** + * 验证属性 表格 + * + * @param instance + * @param instanceValue + * @param property + * @param message + */ + private void validateProperty(Instance instance, InstanceValue instanceValue, Property property, + StringBuilder message) { + String moduleCode = instance.getModuleCode(); + String tablePropertyValue = instanceValue.getPropertyValue(); + String propertyName = property.getName(); + try { + List propertyItems = property.getItemList(); + if (CollectionUtils.isEmpty(propertyItems)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + tablePropertyValue + "] 的结构项不存在\n"); + return; + } + + } catch (Exception e) { + log.error("验证子项失败", e); + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + tablePropertyValue + "] 的选项验证失败\n"); + } + } + + /*** + * 验证属性值是否满足属性约束 + * + * @param property + * @param moduleCode + * @param propertyValue + * @return + */ + private boolean validate(Property property, String moduleCode, Object propertyValue) { + try { + boolean result = true; + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + String propertyType = property.getType(); + if (null != propertyValue && !"null".equalsIgnoreCase(String.valueOf(propertyValue))) { + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + List propertyItems = propertyItemRepository.queryByPropertyId(property.getId()); + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getValue(), propertyItem); + } + if (!propertyItemMap.containsKey(propertyValue)) { + result = false; + } + } else if (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType)) { + List propertyItems = propertyItemRepository.queryByPropertyId(property.getId()); + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getValue(), propertyItem); + } + List values = JSONObject.parseArray(JSON.toJSONString(propertyValue), String.class); + for (String value : values) { + if (!propertyItemMap.containsKey(value)) { + result = false; + break; + } + } + } else if (PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) {// 多行表格 + String propertyIds = property.getPropertyIds(); + if (StringUtils.isEmpty(propertyIds)) { + List propertyItems = + propertyItemRepository.queryByPropertyId(Long.valueOf(property.getId())); + if (CollectionUtils.isEmpty(propertyItems)) { + result = false; + } + } else { + String[] propertyIdsplit = propertyIds.split(","); + for (String propertyId : propertyIdsplit) { + Property cmdbProperty = propertyRepository.query(Long.valueOf(propertyId)); + if (null == cmdbProperty) { + result = false; + break; + } + } + } + } else if (PropertyConstant.PropertyType.INTEGER.equals(propertyType)) { // 验证数值 + if (CmdbUtils.isNumeric(String.valueOf(propertyValue))) { + // 最大值,判断数值 + if (null != property.getMaxValue() + && property.getMaxValue() < Integer.valueOf(String.valueOf(propertyValue))) { + result = false; + } + // 最小值,判断数值 + if (null != property.getMinValue() + && property.getMinValue() > Integer.valueOf(String.valueOf(propertyValue))) { + result = false; + } + } else { + result = false; + } + } else if (PropertyConstant.PropertyType.FLOAT.equals(propertyType)) { + if (CmdbUtils.isNumeric(String.valueOf(propertyValue))) { + if (String.valueOf(propertyValue).contains(".")) { + String num = String.valueOf(propertyValue).split("\\.")[1]; + if (num.length() > property.getDecimalNum()) { + result = false; + } + } else { + result = false; + } + // 最大值,判断数值 + if (null != property.getMaxValue() + && property.getMaxValue().floatValue() < Float.valueOf(String.valueOf(propertyValue))) { + result = false; + } + // 最小值,判断数值 + if (null != property.getMinValue() + && property.getMinValue().floatValue() > Float.valueOf(String.valueOf(propertyValue))) { + result = false; + } + } else { + result = false; + } + } else if (PropertyConstant.PropertyType.BOOLEAN.equals(propertyType) + && !CmdbUtils.isBool(String.valueOf(propertyValue))) { + result = false; + } else if (PropertyConstant.PropertyType.JSON.equals(propertyType) + && !CmdbUtils.isJSON(JSON.toJSONString(propertyValue))) { + result = false; + } else if (PropertyConstant.PropertyType.DATE.equals(propertyType) + && !CmdbUtils.isDate(String.valueOf(propertyValue))) { + result = false; + } else if (PropertyConstant.PropertyType.TIME.equals(propertyType) + && !CmdbUtils.isTime(String.valueOf(propertyValue))) { + result = false; + } + + // 规则表达式 + if (null != property.getRegexpId() && !PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + RegularExpression expression = regularExpressionRepository.query(property.getRegexpId()); + if (null != expression && StringUtils.isNotEmpty(expression.getExpression())) { + boolean flag = CmdbUtils.contains(expression.getExpression(), String.valueOf(propertyValue)); + if (!flag) { + result = false; + } + } + } + } + + // 是否必填 + if (property.getIsRequired() && null != propertyValue + && StringUtils.isEmpty(String.valueOf(propertyValue))) { + result = false; + } + // 是否超过长度限制 + if (PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + // 加密的校验 + if (null != propertyValue && !"null".equalsIgnoreCase(String.valueOf(propertyValue))) { + // 密码解密 + Encryptor encryptor = new AESEncryptor(); + String password = encryptor.decrypt(String.valueOf(propertyValue), null); + if (null != property.getLength() && property.getLength() > 0 && StringUtils.isNotEmpty(password) + && password.length() > property.getLength()) { + result = false; + } + } + } else { + if (null != property.getLength() && property.getLength() > 0 && null != propertyValue + && StringUtils.isNotEmpty(String.valueOf(propertyValue)) + && String.valueOf(propertyValue).length() > property.getLength()) { + result = false; + } + } + // 唯一性 + if (property.getIsUniqued() && null != propertyValue + && StringUtils.isNotEmpty(String.valueOf(propertyValue))) { + InstanceValue checkValue = + instanceValueRepository.query(valueTable, property.getCode(), String.valueOf(propertyValue)); + if (null != checkValue) { + result = false; + } + } + return result; + } catch (Exception e) { + log.error("验证失败", e); + return false; + } + + } + + /*** + * 验证数值 + * + * @param instance + * @param instanceValue + * @param property + * @param message + */ + private void validateNumber(Instance instance, InstanceValue instanceValue, Property property, + StringBuilder message) { + String moduleCode = instance.getModuleCode(); + String propertyValue = instanceValue.getPropertyValue(); + String propertyName = property.getName(); + String propertyType = property.getType(); + try { + if (CmdbUtils.isNumeric(propertyValue)) { + if (PropertyConstant.PropertyType.FLOAT.equals(propertyType)) { + if (propertyValue.contains(".")) { + String num = propertyValue.split("\\.")[1]; + if (num.length() > property.getDecimalNum()) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]保留小数大于[" + + property.getDecimalNum() + "]\n"); + } + } + // 最大值,判断数值 + if (null != property.getMaxValue() + && property.getMaxValue().floatValue() < Float.valueOf(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]大于属性最大值限制[" + + property.getMaxValue() + "]\n"); + } + // 最小值,判断数值 + if (null != property.getMinValue() + && property.getMinValue().floatValue() > Float.valueOf(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]小于属性最小值限制[" + + property.getMinValue() + "]\n"); + } + } else if (PropertyConstant.PropertyType.INTEGER.equals(propertyType)) { + // 最大值,判断数值 + if (null != property.getMaxValue() + && property.getMaxValue().floatValue() < Integer.valueOf(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]大于属性最大值限制[" + + property.getMaxValue() + "]\n"); + } + // 最小值,判断数值 + if (null != property.getMinValue() + && property.getMinValue().floatValue() > Integer.valueOf(propertyValue)) { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]小于属性最小值限制[" + + property.getMinValue() + "]\n"); + } + } + } else { + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "]非数值类型\n"); + + } + } catch (Exception e) { + log.error("验证数值失败", e); + message.append(moduleCode + "实例属性[" + propertyName + "]的值[" + propertyValue + "] 的选项[" + + instanceValue.getPropertyValue() + "]验证数值失败\n"); + } + } + + /*** + * 转换及设置权限 + * + * @param list + * @param moduleId + * @param userId + * @param hasAdminRole + * @throws Exception + */ + @Override + public void convertInstanceValue(List> list, Long moduleId, Long userId, boolean hasAdminRole) + throws Exception { + if (ListTool.isEmpty(list)) { + return; + } + List properties = propertyRepository.listNotHiddenByCmdbModuleId(moduleId); + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getCode(), property); + } + Iterator> iterator = list.iterator(); + while (iterator.hasNext()) { + Long creatorId = 0L; + Map instanceValue = iterator.next(); + Iterator> it = instanceValue.entrySet().iterator(); + Map instanceValueMap = new HashMap<>(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + instanceValueMap.put(entry.getKey(), instanceValue.get(entry.getKey())); + it.remove(); + } + for (String key : instanceValueMap.keySet()) { + // 转换字段为驼峰 + if ("gmt_create".equals(key)) { + // Java 8 date/time type `java.time.LocalDateTime` not supported by default + // 需要针对数据转换 + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String gmtCreate = df.format((LocalDateTime) instanceValueMap.get(key)); + instanceValue.put(CmdbUtils.toCamelCase(key), gmtCreate); + } else if (Common.ID.equals(key) || "module_id".equals(key) || "module_code".equals(key)) { + instanceValue.put(CmdbUtils.toCamelCase(key), instanceValueMap.get(key)); + } else if ("creator_id".equals(key)) { + Object instanceVal = instanceValueMap.get(key); + if (null != instanceVal) { + creatorId = Long.parseLong(instanceVal.toString()); + } + instanceValue.put(CmdbUtils.toCamelCase(key), instanceVal); + } else { + String instanceKey = CmdbUtils.toCamelCase(key); + Object instanceVal = instanceValueMap.get(key); + if (propertyMap.containsKey(instanceKey)) { + Property property = propertyMap.get(instanceKey); + if ((PropertyConstant.PropertyType.CHECKBOX.equals(property.getType()) + || PropertyConstant.PropertyType.MULTISELECT.equals(property.getType()) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(property.getType()) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(property.getType())) + && null != instanceVal && StringUtils.isNotEmpty(String.valueOf(instanceVal))) { + instanceValue.put(instanceKey, JSONTools.parseStr2JsonArray(instanceVal.toString())); + + } else if (PropertyConstant.PropertyType.JSON.equals(property.getType()) && null != instanceVal + && StringUtils.isNotEmpty(String.valueOf(instanceVal))) { + + GeneralResult result = JSONTools.isJSON(instanceVal.toString()); + if (result.isSuccess()) { + instanceValue.put(instanceKey, result.getData()); + } else { + instanceValue.put(instanceKey, JSONTools.parseStr2JsonArray(instanceVal.toString())); + + } + } else { + instanceValue.put(instanceKey, instanceVal); + } + } else { + instanceValue.put(key, instanceVal); + } + } + } + // 设置实例的权限,包括编辑、删除、管理权限 + boolean authEdit = false; + boolean authDelete = false; + boolean authManage = false; + if (hasAdminRole || userId.equals(creatorId)) { + authEdit = true; + authDelete = true; + authManage = true; + } else { + List authorities = instanceAuthorityRepository.listByUserId(moduleId, + Long.valueOf(instanceValue.get(Common.ID).toString()), userId); + for (InstanceAuthority authority : authorities) { + if (StringUtils.isNotEmpty(authority.getAuths()) + && authority.getAuths().contains(InstanceEnum.authority.EDIT.getValue())) { + authEdit = true; + } + if (StringUtils.isNotEmpty(authority.getAuths()) + && authority.getAuths().contains(InstanceEnum.authority.DEL.getValue())) { + authDelete = true; + } + if (StringUtils.isNotEmpty(authority.getAuths()) + && authority.getAuths().contains(InstanceEnum.authority.AUTH_MANAGE.getValue())) { + authManage = true; + } + } + } + instanceValue.put("authEdit", authEdit); + instanceValue.put("authDelete", authDelete); + instanceValue.put("authManage", authManage); + } + } + + /*** + * 单一实例转换 + * + * @param object + * @param moduleId + * @throws Exception + */ + private void convertInstanceValue(JSONObject object, Long moduleId) throws Exception { + if (null == object) { + return; + } + List properties = propertyRepository.listNotHiddenByCmdbModuleId(moduleId); + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getCode(), property); + } + Iterator> it = object.entrySet().iterator(); + Map instanceValueMap = new HashMap<>(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + instanceValueMap.put(entry.getKey(), object.get(entry.getKey())); + it.remove(); + } + for (String key : instanceValueMap.keySet()) { + // 转换字段为驼峰 + if ("gmt_create".equals(key)) { + // Java 8 date/time type `java.time.LocalDateTime` not supported by default + // 需要针对数据转换 + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String gmtCreate = df.format((LocalDateTime) instanceValueMap.get(key)); + object.put(CmdbUtils.toCamelCase(key), gmtCreate); + } else if (Common.ID.equals(key) || "module_id".equals(key) || "module_code".equals(key)) { + object.put(CmdbUtils.toCamelCase(key), instanceValueMap.get(key)); + } else { + String instanceKey = CmdbUtils.toCamelCase(key); + Object instanceVal = instanceValueMap.get(key); + if (propertyMap.containsKey(instanceKey)) { + Property property = propertyMap.get(instanceKey); + if ((PropertyConstant.PropertyType.CHECKBOX.equals(property.getType()) + || PropertyConstant.PropertyType.MULTISELECT.equals(property.getType()) + || PropertyConstant.PropertyType.JSON.equals(property.getType()) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(property.getType()) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(property.getType())) + && null != instanceVal && StringUtils.isNotEmpty(String.valueOf(instanceVal))) { + GeneralResult result = JSONTools.isJSON(instanceVal.toString()); + if (result.isSuccess()) { + object.put(instanceKey, JSONObject.parseObject(instanceVal.toString())); + } else { + object.put(instanceKey, JSONArray.parseArray(instanceVal.toString())); + } + } else { + object.put(instanceKey, instanceVal); + } + } + } + } + } + + /*** + * 检查当前用户是否有超级管理员的角色 + * + * @param userId + * @return + */ + @Override + public boolean checkAdminRole(Long userId) { + boolean hasAdminRole = false; + GeneralResult roleResult = smsInternalService.getRolesByUserId(userId); + if (roleResult.isFailed()) { + log.error("查询当前用户角色失败:{}", roleResult.getMessage()); + return false; + } + List roles = JSONObject.parseArray(JSONObject.toJSONString(roleResult.getData()), Role.class); + for (Role role : roles) { + // 1 == role.getId() 超级管理员 + if (1 == role.getId()) { + hasAdminRole = true; + break; + } + } + return hasAdminRole; + } + + @Override + public GeneralResult download(Long moduleId, String moduleCode, String type, Long userId) { + Workbook workbook = null; + try { + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return new GeneralResult<>(false, "模型数据不存在"); + } + if (!moduleCode.equals(module.getCode())) { + return new GeneralResult<>(false, "模型数据不存在"); + } + List properties = queryModulePropertys(module.getId()); + List propertieList = new ArrayList<>(); + // 移除uuid字段及单行文本中的内置函数、流水号和自增id + for (Property property : properties) { + if (Common.UUID.equals(property.getCode())) { + continue; + } + // 单行文本中流水号、自增、内置函数不校验数据规则,值代码中自动生成 + String defaultValueType = property.getDefaultValueType(); + if (PropertyConstant.PropertyType.TEXTFIELD.equals(property.getType())) { + if (PropertyConstant.DefaultValueType.SERIALNUM.equalsIgnoreCase(defaultValueType) + || PropertyConstant.DefaultValueType.AUTOINCRID.equalsIgnoreCase(defaultValueType) + || PropertyConstant.DefaultValueType.INNERFUN.equalsIgnoreCase(defaultValueType)) { + continue; + } + } + propertieList.add(property); + } + + String fileName = module.getName() + "-实例模板.xls"; + if ("2007".equals(type)) { + fileName = fileName + "x"; + } + workbook = new ExcelFactory(fileName).newWorkbook(); + // 构建表头 + excelHelper.generateTemplateSheet(workbook, module, propertieList); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + workbook.write(baos); + byte[] ba = baos.toByteArray(); + Map resultMap = Maps.newHashMap(); + resultMap.put("fileName", fileName); + resultMap.put("data", Base64.getEncoder().encodeToString(ba)); + return new GeneralResult<>(true, resultMap, "模板下载成功"); + } catch (Exception e) { + log.error("instance template download fail:", e); + return new GeneralResult<>(false, "模板下载失败"); + } + } + + @Override + public GeneralResult upload(Long moduleId, String moduleCode, MultipartFile excel, RequestContext context) { + try { + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return new GeneralResult<>(false, "模型数据不存在"); + } + if (!moduleCode.equals(module.getCode())) { + return new GeneralResult<>(false, "模型数据不存在"); + } + List properties = queryModulePropertys(module.getId()); + // 移除uuid字段 + List propertieList = + properties.stream().filter(item -> !Common.UUID.equals(item.getCode())).collect(Collectors.toList()); + String fileName = URLDecoder.decode(excel.getOriginalFilename(), "UTF-8"); + ExcelFactory excelFactory; + excelFactory = new ExcelFactory(excel.getInputStream(), fileName); + Workbook wb = excelFactory.newWorkbook(); + String uuid = IDFactory.instance().uuid(); + taskExecutor.execute(() -> { + this.uploadInstances(uuid, wb, moduleId, moduleCode, propertieList, context); + }); + } catch (Exception e) { + log.error("实例数据导入失败", e); + return new GeneralResult<>(false, "实例数据导入失败"); + } + return new GeneralResult<>(true, "实例数据导入任务已下发"); + } + + private List queryModulePropertys(Long id) { + List propertys = new ArrayList<>(); + GeneralResult result = property(id); + if (result.isSuccess()) { + propertys = result.getData().getProperties(); + } + return propertys; + } + + public GeneralResult property(Long moduleId) { + try { + List groups = propertyGroupRepository.listByModuleId(moduleId); + List properties = propertyRepository.listNotHiddenByCmdbModuleId(moduleId); + List items = propertyItemRepository.queryByModuleId(moduleId); + for (Property property : properties) { + propertyService.propertyHandle(property, items); + } + PropertyModel model = new PropertyModel(moduleId, groups, properties); + return new GeneralResult<>(true, model, "查询属性成功"); + } catch (Exception e) { + log.error("moduleService property fail:", e); + return new GeneralResult<>(false, "查询属性失败"); + } + } + + @Override + public GeneralResult topo(Long id, Long relationCategoryId, Long moduleId, Long userId) { + try { + RelationCategory relationCategory = relationCategoryRepository.query(relationCategoryId); + if (null == relationCategory) { + return new GeneralResult<>(false, "关系分类不存在"); + } + String relationCategoryCode = relationCategory.getCode(); + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return new GeneralResult<>(false, "模型不存在"); + } + + String moduleCode = module.getCode(); + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + String instanceRelationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategoryCode.toLowerCase(); + Instance instance = instanceRepository.query(instanceTable, id); + InstanceValue instanceValue = instanceValueRepository.query(instanceValueTable, Common.NAME, id); + if (null == instance || null == instanceValue) { + return new GeneralResult<>(false, "实例不存在"); + } + List moduleRelations = + moduleRelationRepository.queryAll(relationCategory.getId(), moduleId); + if (CollectionUtils.isEmpty(moduleRelations)) { + InstanceTopo topo = new InstanceTopo(); + // 查询当前实例 + InstanceModel instanceModel = new InstanceModel(); + instanceModel.setInstanceId(id); + instanceModel.setInstanceName(instanceValue.getPropertyValue()); + instanceModel.setModuleId(instance.getModuleId()); + instanceModel.setModuleCode(instance.getModuleCode()); + instanceModel.setIconImage(module.getIconImage()); + topo.setNodes(Arrays.asList(instanceModel)); + topo.setLinks(new ArrayList<>()); + return new GeneralResult<>(true, topo, "模型关系不存在"); + } + // 反向模型关系名称 + Map relationReversedMap = new HashMap<>(); + Map relationMap = new HashMap<>(); + for (ModuleRelation relation : moduleRelations) { + relationReversedMap.put(relation.getId(), + relation.getTargetName() + relation.getRelationReverseName() + relation.getSourceName()); + relationMap.put(relation.getId(), + relation.getSourceName() + relation.getRelationName() + relation.getTargetName()); + } + List instanceRelations = new ArrayList<>(); + List sourceInstanceRelations = + instanceRelationRepository.querySources(instanceRelationTable, moduleId, id); + List targetInstanceRelations = + instanceRelationRepository.queryTargets(instanceRelationTable, moduleId, id); + instanceRelations.addAll(sourceInstanceRelations); + instanceRelations.addAll(targetInstanceRelations); + // 所有实例 moduleCode+"-"+moduleId+"-"+instanceId + Set instanceSet = new HashSet<>(); + // 放入自身 + instanceSet.add(moduleCode + "-" + moduleId + "-" + id); + List nodes = new ArrayList<>(); + List links = new ArrayList<>(); + + for (InstanceRelation relation : instanceRelations) { + instanceSet.add(relation.getSourceModuleCode() + "-" + relation.getSourceModuleId() + "-" + + relation.getSourceInstanceId()); + instanceSet.add(relation.getTargetModuleCode() + "-" + relation.getTargetModuleId() + "-" + + relation.getTargetInstanceId()); + // 放入link + InstanceRelationModel link = new InstanceRelationModel(); + BeanUtils.copyProperties(relation, link); + link.setRelationId(relation.getModuleRelationId()); + link.setRelationName(relation.getModuleRelationName()); + // 反向的时候,箭头相反相关信息 + if (relation.getIsReversed()) { + link.setRelationName(relationReversedMap.get(relation.getModuleRelationId())); + link.setType(relation.getTargetType() + "-" + relation.getSourceType()); + + // 反向的时候源和目标信息对调 + link.setSourceInstanceId(relation.getTargetInstanceId()); + link.setSourceInstanceName(relation.getTargetInstanceName()); + link.setSourceModuleCode(relation.getTargetModuleCode()); + link.setSourceModuleId(relation.getTargetModuleId()); + link.setTargetInstanceId(relation.getSourceInstanceId()); + link.setTargetInstanceName(relation.getSourceInstanceName()); + link.setTargetModuleCode(relation.getSourceModuleCode()); + link.setTargetModuleId(relation.getSourceModuleId()); + } else { + link.setRelationName(relationMap.get(relation.getModuleRelationId())); + link.setType(relation.getSourceType() + "-" + relation.getTargetType()); + } + links.add(link); + } + + if (instanceSet.size() > 0) { + Iterator instances = instanceSet.iterator(); + while (instances.hasNext()) { + InstanceModel instanceModel = new InstanceModel(); + String ins = instances.next(); + String[] insSplit = ins.split("-"); + String insModuleCode = insSplit[0]; + Long insModuleId = Long.valueOf(insSplit[1]); + Long insId = Long.valueOf(insSplit[2]); + module = moduleRepository.query(insModuleId); + instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + insModuleCode.toLowerCase(); + instanceValue = instanceValueRepository.query(instanceValueTable, Common.NAME, insId); + if (null == module || null == instanceValue) { + continue; + } + instanceModel.setInstanceId(insId); + instanceModel.setInstanceName(instanceValue.getPropertyValue()); + instanceModel.setModuleId(insModuleId); + instanceModel.setModuleCode(insModuleCode); + instanceModel.setIconImage(module.getIconImage()); + nodes.add(instanceModel); + } + } + InstanceTopo topo = new InstanceTopo(); + topo.setNodes(nodes); + topo.setLinks(links); + return new GeneralResult<>(true, topo, "实例拓扑查询成功"); + } catch (Exception e) { + log.error("Cmdb instance topo query fail:", e); + return new GeneralResult<>(false, "实例拓扑查询失败"); + } + } + + public void uploadInstances(String uuid, Workbook wb, Long moduleId, String moduleCode, List properties, + RequestContext context) { + boolean validateSuccess = true; + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getName(), property); + } + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleCode.toLowerCase(); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + try { + validataWb(wb, propertyMap); + } catch (Exception e) { + validateSuccess = false; + } + int total = countDataNum(wb); + int success = 0; + int fail = 0; + if (validateSuccess) { + // 遍历sheet页 + for (int n = 0; n < wb.getNumberOfSheets(); n++) { + try { + Sheet sheet = wb.getSheetAt(n); + // 属性 + Map header = ExcelHelper.readHeader4NameKey(sheet.getRow(0), 1); + Map headerProperty = Maps.newHashMap(); + for (Property property : properties) { + Integer index = header.get(property.getName()); + String propertyType = property.getType(); + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType) + || PropertyConstant.PropertyType.CHECKBOX.equals(propertyType)) { + List items = property.getItemList(); + property.setItemList(items); + } + if (null != index && index > 0) { + headerProperty.put(index, property); + } + } + // 表头单元格开始位置,依次每行按照其索引位置开始读取 + int startIndex = 1; + // 最后一列数 + int lastColumn = header.size() + startIndex; + // 遍历行 + for (int i = 2; i <= sheet.getLastRowNum(); i++) { + + Row row = sheet.getRow(i); + if (row == null) { + throw new Exception("请检查第" + (i + 1) + "行下面是否有干扰数据。"); + } + JSONObject instanceValueObj = new JSONObject(); + for (int j = startIndex; j < lastColumn; j++) { + Cell cell = row.getCell(j); + Property property = headerProperty.get(new Integer(j)); + if (null != property) { + String propertyType = property.getType(); + String propertyCode = property.getCode(); + Object propertyValue = ExcelHelper.getCellValue(cell); + // 导出的模板显示的是name,需要重新赋值 + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + for (PropertyItem item : items) { + if (item.getName().equals(propertyValue)) { + propertyValue = item.getValue(); + } + } + } + } else if (PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.CHECKBOX.equals(propertyType)) { + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + List itemValueList = new ArrayList<>(); + Map itemMap = new HashMap<>(); + for (PropertyItem item : items) { + itemMap.put(item.getName(), item); + } + if (StringUtils.isNotEmpty(String.valueOf(propertyValue))) { + String[] propertyValues = String.valueOf(propertyValue).split(","); + for (String value : propertyValues) { + if (itemMap.containsKey(value)) { + itemValueList.add(itemMap.get(value).getValue()); + } + } + } + propertyValue = itemValueList; + } + } else if (PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + + if (StringUtils.isEmpty(String.valueOf(propertyValue))) { + propertyValue = new JSONArray(); + } else { + propertyValue = JSONArray.parseArray(propertyValue.toString()); + } + } else if (PropertyConstant.PropertyType.JSON.equals(propertyType)) { + if (StringUtils.isNotEmpty(String.valueOf(propertyValue))) { + GeneralResult result = JSONTools.isJSON(String.valueOf(propertyValue)); + if (result.isSuccess()) { + propertyValue = result.getData(); + } else { + JSONArray array = JSONTools.parseStr2JsonArray(String.valueOf(propertyValue)); + if (null != array) { + propertyValue = array; + } else { + log.error("json类型属性格式有误{}", propertyValue); + } + + } + } else { + //json默认值为空对象 {} + propertyValue = new JSONObject(); + } + + } else if (PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + + if (StringUtils.isNotEmpty(String.valueOf(propertyValue))) { + //密码加密,和页面添加实例密文加密方式一致 + AESEncryptor encrptor = new AESEncryptor(); + propertyValue = encrptor.encrypt(String.valueOf(propertyValue), null); + } + } + instanceValueObj.put(propertyCode, propertyValue); + } + } + instanceValueObj.put("moduleId", moduleId); + instanceValueObj.put("moduleCode", moduleCode); + // 当前存在的实例 + List instances = instanceRepository.queryByModuleId(instanceTable, instanceValueTable, + moduleId, Common.NAME); + Map instanceMap = new HashMap<>(); + for (Instance instance : instances) { + instanceMap.put(instance.getName(), instance); + } + GeneralResult result = new GeneralResult(false, "导入失败"); + // 判断是否存在,存在即更新 + if (instanceMap.containsKey(instanceValueObj.getString(Common.NAME))) { + instanceValueObj.put(Common.ID, + instanceMap.get(instanceValueObj.getString(Common.NAME)).getId()); + result = this.modify(instanceValueObj, context.getTarget()); + } else { + result = this.create(instanceValueObj, context.getTarget(), true); + } + if (result.isSuccess()) { + success++; + } else { + fail++; + } + ExcelHelper.promptErrorMessage(row, result.getMessage()); + processMessage(uuid, context, total, success, fail); + } + } catch (Exception e) { + total = 0; + wb.getSheetAt(0).setColumnWidth(0, 20000); + ExcelHelper.promptErrorMessage(wb, e.getMessage()); + log.info("导入失败", e); + } + } + } else { + processMessage(uuid, context, 0, 0, 0); + } + } + + private void processMessage(String uuid, RequestContext context, int total, int success, int fail) { + Map messageContent = Maps.newHashMap(); + messageContent.put("total", total); + if (total == 0) { + messageContent.put("progress", 100); + messageContent.put("success", 0); + messageContent.put("fail", "fail"); + } else { + BigDecimal progress = new BigDecimal(success + fail).multiply(new BigDecimal(100)) + .divide(new BigDecimal(total), 10, RoundingMode.HALF_DOWN); + double progresses = Math.floor(progress.doubleValue()); + messageContent.put("progress", progresses); + + if (progresses == progressLast && progresses != 100) { + return; + } + progressLast = progresses; + messageContent.put("success", success); + messageContent.put("fail", fail); + } + messageContent.put("uuid", uuid); + eventPublisher.send(new OperateResult(true, "导入进度推送", "cmdb_instance", messageContent, + OperateResult.OperateCategory.CMDBIMPORT, context)); + } + + private void validataWb(Workbook wb, Map propertyMap) throws Exception { + for (int n = 0; n < wb.getNumberOfSheets(); n++) { + Sheet sheet = wb.getSheetAt(n); + Map header = ExcelHelper.readHeader4NameKey(sheet.getRow(0), 1); + Set propNotContain = new HashSet<>(); + for (String name : header.keySet()) { + if (!propertyMap.containsKey(name)) { + propNotContain.add(name); + } + } + if (!propNotContain.isEmpty()) { + throw new Exception("表头中缺少以下属性:" + propNotContain.toString()); + } + } + } + + private int countDataNum(Workbook wb) { + int total = 0; + for (int n = 0; n < wb.getNumberOfSheets(); n++) { + Sheet sheet = wb.getSheetAt(n); + total += ExcelHelper.getRowNumberOfSheet(sheet) - 2; + } + return total; + + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceValueServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceValueServiceImpl.java new file mode 100644 index 0000000..8292585 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/instance/impl/InstanceValueServiceImpl.java @@ -0,0 +1,59 @@ +package com.bocloud.ams.service.instance.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceValueService; +import com.megatron.common.model.GeneralResult; + +import lombok.extern.slf4j.Slf4j; + +/** + * @ClassName: CmdbInstanceValueServiceImpl + * @Description + * @Author yangzhenrong + * @Date 2022/5/11 11:25 + * @Version 1.0 + **/ +@Slf4j +@Service("instanceValueService") +public class InstanceValueServiceImpl implements InstanceValueService { + + @Autowired + private InstanceValueRepository instanceValueRepository; + + @Override + public GeneralResult createTable(String moduleCode, Long userId) { + try { + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + if (instanceValueRepository.countTable(valueTable) > 0) { + log.warn("创建表空间{}失败", valueTable); + return new GeneralResult<>(false, "创建失败"); + } + instanceValueRepository.createTable(valueTable, new InstanceValue()); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("create module instance value table error:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + public GeneralResult dropTable(String moduleCode, Long userId) { + try { + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase(); + if (instanceValueRepository.countTable(valueTable) == 0) { + log.warn("删除表空间{}失败", valueTable); + return new GeneralResult<>(false, "删除失败"); + } + instanceValueRepository.dropTable(valueTable); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("drop module instance value table error:", e); + return new GeneralResult<>(false, "删除失败"); + } + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/AmsInternalService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/AmsInternalService.java new file mode 100644 index 0000000..7aa2d5c --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/AmsInternalService.java @@ -0,0 +1,58 @@ +package com.bocloud.ams.service.internal; + + +import com.bocloud.cmp.boot.model.BocloudToken; +import com.megatron.common.model.GeneralResult; +import com.megatron.framework.core.CurrentService; +import com.megatron.framework.http.core.HttpMethod; +import com.megatron.framework.http.core.ServiceFactory; +import com.megatron.framework.http.model.RemoteService; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/6/16 11:02 + */ +@Service +public class AmsInternalService implements InitializingBean { + private Map headers = new HashMap<>(4); + private static final com.megatron.framework.core.Service SERVICE = com.megatron.framework.core.Service.create("ams"); + + @Autowired + private ServiceFactory serviceFactory; + @Autowired + private CurrentService currentService; + + public boolean scheduleInspectBroadcast(Long id, HttpMethod method) { + boolean success = false; + String taskUrl = "/v1/collection/tasks/" + id + "/schedule"; + List services = serviceFactory.buildAll(SERVICE, taskUrl, method, headers, null); + for (RemoteService service : services) { + GeneralResult result = service.invoke(); + if (result.isFailed()) { + continue; + } + if ("fixed".equals(result.getData().toString())) { + success = true; + break; + } + } + return success; + } + + @Override + public void afterPropertiesSet() throws Exception { + this.headers.put(BocloudToken.INTERNAL_TOKEN, currentService.getToken()); + this.headers.put("source", currentService.getService().getName()); + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/SmsInternalService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/SmsInternalService.java new file mode 100644 index 0000000..3653e41 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/internal/SmsInternalService.java @@ -0,0 +1,62 @@ +package com.bocloud.ams.service.internal; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.Role; +import com.bocloud.cmp.boot.model.BoCloudService; +import com.megatron.framework.core.Service; +import com.bocloud.cmp.boot.model.BocloudToken; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.core.CurrentService; +import com.megatron.framework.core.Service; +import com.megatron.framework.http.core.HttpMethod; +import com.megatron.framework.http.core.ServiceFactory; +import com.megatron.framework.http.model.RemoteService; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class SmsInternalService implements InitializingBean { + + private final ServiceFactory serviceFactory; + private final CurrentService currentService; + + @Autowired + public SmsInternalService(ServiceFactory serviceFactory, CurrentService currentService) { + this.serviceFactory = serviceFactory; + this.currentService = currentService; + } + + private static final Service SERVICE = Service.create(BoCloudService.SMS.getName()); + private final Map headers = new HashMap<>(4); + + public GeneralResult detail(Long userId) { + String url = "/v1/users/" + userId; + RemoteService remoteService = serviceFactory.build(SERVICE, url, HttpMethod.GET, headers, null); + GeneralResult result = remoteService.invoke(); + if (result.isFailed()) { + return new GeneralResult<>(false, result.getMessage()); + } + String data = JSONObject.toJSONString(result.getData()); + return new GeneralResult<>(true, JSONObject.parseObject(data), "success"); + } + + public GeneralResult> getRolesByUserId(Long userId) { + String url = "/v1/users/" + userId + "/roles"; + RemoteService remoteService = serviceFactory.build(SERVICE, url, HttpMethod.GET, headers, MapTools.simpleMap(Common.CONDITION, "cmdbQueryRoles")); + return (GeneralResult>) remoteService.invoke(); + } + + @Override + public void afterPropertiesSet() throws Exception { + this.headers.put(BocloudToken.INTERNAL_TOKEN, currentService.getToken()); + this.headers.put("source", currentService.getService().getName()); + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleGroupService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleGroupService.java new file mode 100644 index 0000000..e72db69 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleGroupService.java @@ -0,0 +1,35 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.module.ModuleGroup; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.RequestContext; + +import java.util.List; + +/** + * @Author 胡立伟 + * @Date 2022/4/29 0029 16:12 + * @Description: + */ +public interface ModuleGroupService { + + GeneralResult> collections(String category, String moduleName); + + GeneralResult> queryRoot(); + + GeneralResult> queryRootChildren(); + + GeneralResult save(ModuleGroup group, Long target); + + GeneralResult detail(Long id); + + GeneralResult modify(ModuleGroup group, Long target); + + GeneralResult queryChildren(Long groupId, String menu, RequestContext context); + + GeneralResult remove(Long id, Long userId); + + GeneralResult> querylist(); + + GeneralResult> queryRootChildren(Long groupId, String menu, RequestContext context); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleRelationService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleRelationService.java new file mode 100644 index 0000000..21a3046 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleRelationService.java @@ -0,0 +1,76 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.model.ModuleTopo; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; + +import java.util.List; + +public interface ModuleRelationService { + /** + * 添加 + * + * @param relation + * @return + */ + public GeneralResult create(ModuleRelation relation, Long userId); + + /** + * 修改 + * + * @param relation + * @return + */ + public GeneralResult modify(ModuleRelation relation, Long userId); + + public GeneralResult detail(Long id); + + /** + * 删除 + * + * @param id + * @return + */ + public GeneralResult remove(Long id, Long userId); + + /** + * 查询所有 + * + * @param moduleId 模型id + * @param relationCategoryId 关联类型分组id + */ + GeneralResult list(Long moduleId, Long relationCategoryId); + + /** + * 查询所有 + * + * @param relationCategoryId 关联类型分组id + */ + GeneralResult listByCategoryId(Long relationCategoryId); + + /** + * @param relationCategoryId + * @param sourceId + * @param targetId + * @Description: 根据拓扑,模型数据查询模型关系 + */ + GeneralResult relevancy(Long relationCategoryId, Long sourceId, Long targetId); + + /** + * 关联类型分组id查询模型集合 + * + * @param relationCategoryId + * @return + */ + GeneralResult> moduleList(Long relationCategoryId); + + /*** + * 根据模型关系及指定模型获取模型实例 + * @param pager + * @param userId + * @return + */ + GeneralResult instances(Pager pager, Long userId); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleService.java new file mode 100644 index 0000000..bbf6306 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/ModuleService.java @@ -0,0 +1,38 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.model.PropertyModel; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.Property; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.RequestContext; + +import java.util.List; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 11:54 + */ +public interface ModuleService { + + GeneralResult> getModelList(Pager pager); + + GeneralResult> list(); + + GeneralResult detail(Long id); + + GeneralResult save(CiModule module, Long target); + + GeneralResult remove(Long id, Long userId); + + GeneralResult modify(CiModule module, Long target); + + GeneralResult property(Long id); + + GeneralResult> propertyList(Long moduleId, Pager pager); + + GeneralResult modifyProperty(PropertyModel model, Long id, RequestContext context); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyPoolService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyPoolService.java new file mode 100644 index 0000000..8da3172 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyPoolService.java @@ -0,0 +1,47 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.module.PropertyPool; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; + +public interface PropertyPoolService { + /** + * 添加 + * + * @param pool + * @return + */ + public GeneralResult create(PropertyPool pool, Long userId); + + /** + * 修改 + * + * @param pool + * @return + */ + public GeneralResult modify(PropertyPool pool, Long userId); + + /** + * 删除 + * + * @param id + * @return + */ + public GeneralResult remove(Long id, Long userId); + + /** + * 获取详情 + * + * @param id + * @return + */ + public GeneralResult detail(Long id); + + /** + * 列表分页查询 + * + * @param pager + * @return + */ + public GeneralResult list(Pager pager); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyService.java new file mode 100644 index 0000000..5095d14 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/PropertyService.java @@ -0,0 +1,18 @@ +package com.bocloud.ams.service.module; + +import java.util.List; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyItem; +import com.megatron.common.model.GeneralResult; + +/** + * @Author 胡立伟 + * @Date 2022/5/9 0009 18:28 + * @Description: + */ +public interface PropertyService { + + GeneralResult detail(Long id); + + void propertyHandle(final Property property, final List items) throws Exception; +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RegularExpressionService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RegularExpressionService.java new file mode 100644 index 0000000..950b950 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RegularExpressionService.java @@ -0,0 +1,23 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.module.RegularExpression; +import com.megatron.common.model.GeneralResult; + +import java.util.List; + +/** + * CiRegularExpression Service层 + * + * @author 胡立伟 + * @Version 1.0 + * @since 2017年9月15日 + */ +public interface RegularExpressionService { + + /** + * 查询列表 + * + * @return + */ + GeneralResult> list(String type); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationCategoryService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationCategoryService.java new file mode 100644 index 0000000..ccc5f20 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationCategoryService.java @@ -0,0 +1,64 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; + +import java.util.List; +import java.util.Map; + +public interface RelationCategoryService { + /** + * 添加 + * + * @param relationCategory + * @return + */ + public GeneralResult create(RelationCategory relationCategory, Long userId); + + /** + * 修改 + * + * @param relationCategory + * @return + */ + public GeneralResult modify(RelationCategory relationCategory, Long userId); + + /** + * 删除 + * + * @param id + * @return + */ + public GeneralResult remove(Long id, Long userId); + + /** + * 列表分页查询 + * + * @param pager + * @return + */ + public GeneralResult list(Pager pager); + + /** + * 列表分页查询 + * + * @param param + * @param sorter + * @return + */ + public GeneralResult listAll(List param, Map sorter); + + /*** + * 根据关系分组及模型获取模型关系 + * @param id + * @param moduleId + * @return + */ + GeneralResult> moduleRelationList(Long id, Long moduleId); + + GeneralResult listByModuleId(Long moduleId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationService.java new file mode 100644 index 0000000..4fc07f6 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/RelationService.java @@ -0,0 +1,40 @@ +package com.bocloud.ams.service.module; + +import com.bocloud.ams.entity.module.Relation; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Pager; + +public interface RelationService { + /** + * 添加 + * + * @param relation + * @return + */ + public GeneralResult create(Relation relation, Long userId); + + /** + * 修改 + * + * @param relation + * @return + */ + public GeneralResult modify(Relation relation, Long userId); + + /** + * 删除 + * + * @param id + * @return + */ + public GeneralResult remove(Long id, Long userId); + + + /** + * 列表分页查询 + * + * @param pager + * @return + */ + public GeneralResult list(Pager pager); +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/TopologyConfigService.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/TopologyConfigService.java new file mode 100644 index 0000000..677cb75 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/TopologyConfigService.java @@ -0,0 +1,149 @@ +package com.bocloud.ams.service.module; + +import java.util.List; +import java.util.Map; + +import com.bocloud.ams.entity.model.ColumnAndSearchItemModel; +import com.bocloud.ams.entity.model.InstanceTopo; +import com.bocloud.ams.entity.model.PathModel; +import com.bocloud.ams.entity.model.ResponseInstanceTopologyModel; +import com.bocloud.ams.entity.module.TopologyConfig; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; + +import jakarta.servlet.http.HttpServletResponse; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/12 17:40 + */ +public interface TopologyConfigService { + + /** + * 列表分页查询 + * + * @param pager + * @return + */ + GeneralResult> list(Pager pager); + + /** + * 新增模型 + * + * @param config + * @param target + * @return + */ + GeneralResult save(TopologyConfig config, Long target); + + /** + * 更新模型 + * + * @param config + * @param target + * @return + */ + GeneralResult modify(TopologyConfig config, Long target); + + /** + * 删除拓扑实例 + * + * @param id + * @param target + * @return + */ + GeneralResult remove(Long id, Long target); + + /** + * 查询实例拓扑详情 + * + * @param id + * @return + */ + GeneralResult detail(Long id); + + /** + * 根据起始模型查询最大拓扑层级 + * + * @param categoryId + * @param startModuleId + * @return + */ + GeneralResult maxLevel(Long categoryId, Long startModuleId); + + /** + * 获取拓扑路径 + * + * @param categoryId + * @param startModuleId + * @param topologyLevel + * @param ignoreModuleId + * @param wayModuleId + * @return + */ + GeneralResult> topologyPath(Long categoryId, Long startModuleId, Integer topologyLevel, + String ignoreModuleId, String wayModuleId); + + /** + * 获取查询项以及列表项 + * + * @param id + * @return + */ + GeneralResult searchItemList(Long id); + + /** + * 查询资源列表 + * + * @param pager + * @return + */ + GeneralResult>> resourcelist(Pager pager); + + /** + * 根据实例拓扑id查询对应起始模型的实例集合 + * + * @param id + * @return + */ + GeneralResult> startModuleInstanceList(Long id); + + /** + * R + * 下载 + * + * @param response + */ + GeneralResult download(Long id, HttpServletResponse response); + + /** + * 实例拓扑-全局拓扑 + * + * @param id + * @param instanceId + * @return + */ + GeneralResult topoList(Long id, Long instanceId); + + /** + * 实例资源拓扑 + * + * @param id + * @param instanceId + * @return + */ + GeneralResult topology(Long id, Long instanceId); + + /** + * 实例拓扑-根据实例id查找下一层级实例拓扑 + * + * @param id + * @param instanceId + * @return + */ + GeneralResult nextTopoList(Long id, Long moduleId, Long instanceId); + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleGroupServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleGroupServiceImpl.java new file mode 100644 index 0000000..c894d2d --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleGroupServiceImpl.java @@ -0,0 +1,573 @@ +package com.bocloud.ams.service.module.impl; + +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleGroup; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.module.ModuleGroupRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceService; +import com.bocloud.ams.service.module.ModuleGroupService; +import com.bocloud.ams.service.utils.ModuleConstant; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Param; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.Sign; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @Author 胡立伟 + * @Date 2022/4/29 0029 16:13 + * @Description: + */ +@Slf4j +@Service("moduleGroupService") +public class ModuleGroupServiceImpl implements ModuleGroupService { + @Autowired + private ModuleGroupRepository moduleGroupRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceService instanceService; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private ThreadPoolTaskExecutor threadPoolTaskExecutor; + + @Override + public GeneralResult> collections(String category, String moduleName) { + try { + // 获取模型分组所有数据 + List groups = moduleGroupRepository.all(); + if (CollectionUtils.isEmpty(groups)) { + return new GeneralResult<>(true, groups, "查询成功"); + } + List parents = + groups.stream().filter(item -> item.getParentId().equals(0L)).collect(Collectors.toList()); + // 对模型分组根据parentId进行分组 + Map> groupMap = + groups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + if ("template".equalsIgnoreCase(category)) { + // 查询模型下存在采集模板的模型 + List template = moduleRepository.existCollectionTemplate(moduleName); + Map> moduleMap = + template.stream().collect(Collectors.groupingBy(CiModule::getGroupId)); + this.getTree(parents, groupMap, moduleMap); + } else if ("task".equalsIgnoreCase(category)) { + // 查询模型下存在采集任务的模型 + List task = moduleRepository.existCollectionTask(moduleName); + Map> moduleMap = task.stream().collect(Collectors.groupingBy(CiModule::getGroupId)); + this.getTree(parents, groupMap, moduleMap); + } + return new GeneralResult<>(true, filterData(parents), "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService collections fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private List filterData(List parents) { + List groups = parents.stream().filter(group -> { + return !(null == group.getChildrenGroups() && null == group.getModules()); + }).collect(Collectors.toList()); + return groups; + } + + private Boolean getTree(List parents, Map> groupMap, + Map> moduleMap) { + Boolean exist = false; + if (null == parents) { + return false; + } + Iterator iterator = parents.iterator(); + while (iterator.hasNext()) { + ModuleGroup group = iterator.next(); + List children = groupMap.get(group.getId()); + // 当前节点不存在下级节点及模型数据直接剔除 + if (moduleMap.containsKey(group.getId())) { + group.setModules(moduleMap.get(group.getId())); + exist = true; + } else { + if (null == children) { + iterator.remove(); + continue; + } + } + if (this.getTree(children, groupMap, moduleMap)) { + group.setChildrenGroups(children); + exist = true; + } + } + return exist; + } + + @Override + public GeneralResult> queryRoot() { + try { + List rootGroups = moduleGroupRepository.queryRoot(); + if (CollectionUtils.isEmpty(rootGroups)) { + return new GeneralResult<>(true, rootGroups, "查询成功"); + } + List rootGroupIds = rootGroups.stream().map(ModuleGroup::getId).collect(Collectors.toList()); + // 获取模型分组所有数据 + List moduleGroups = moduleGroupRepository.all(); + // 获取根节点的子节点集合 + List children = moduleGroups.stream().filter(item -> rootGroupIds.contains(item.getParentId())) + .collect(Collectors.toList()); + // 获取模型所有数据 + List modules = moduleRepository.all(); + // 对模型根据groupId进行分组 + Map> moduleMap = modules.stream().filter(item -> null != item.getGroupId()) + .collect(Collectors.groupingBy(CiModule::getGroupId)); + // 判断根节点是否包含子节点以及模型 + for (ModuleGroup moduleGroup : rootGroups) { + List childGroups = children.stream() + .filter(item -> item.getParentId().equals(moduleGroup.getId())).collect(Collectors.toList()); + List childMudules = moduleMap.get(moduleGroup.getId()); + if (CollectionUtils.isEmpty(childGroups) && CollectionUtils.isEmpty(childMudules)) { + moduleGroup.setExistNextData(false); + } else { + moduleGroup.setExistNextData(true); + } + } + return new GeneralResult<>(true, rootGroups, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService queryRoot fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> queryRootChildren() { + try { + // 获取模型分组所有数据 + List groups = moduleGroupRepository.all(); + List parent = + groups.stream().filter(item -> item.getParentId().equals(0L)).collect(Collectors.toList()); + // 对模型分组根据parentId进行分组 + Map> groupMap = + groups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + if (CollectionUtils.isNotEmpty(parent)) { + this.getRootTree(parent, groupMap); + } + return new GeneralResult<>(true, parent, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService queryRootChildren fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult save(ModuleGroup group, Long target) { + try { + if ("其他".equals(group.getName())) { + return new GeneralResult<>(false, "添加失败,当前分组名称为非法名称,请尝试其他名称"); + } + int sameName = moduleGroupRepository.countSameNameOrCode(group.getName(), null); + if (sameName > 0) { + return new GeneralResult<>(false, "添加失败,该名称已存在,请尝试其他名称"); + } + int sameCode = moduleGroupRepository.countSameNameOrCode(null, group.getCode()); + if (sameCode > 0) { + return new GeneralResult<>(false, "添加失败,该编码已存在,请尝试其他编码"); + } + if (null == group.getParentId()) { + group.setParentId(0L); + } + group.setGmtCreate(new Date()); + group.setCreatorId(target); + group.setMenderId(target); + moduleGroupRepository.save(group); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("moduleGroupService save fail:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + ModuleGroup group = moduleGroupRepository.query(id); + return new GeneralResult<>(true, group, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService detail fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult modify(ModuleGroup group, Long target) { + String path = ModuleGroup.class.getSimpleName() + "_" + group.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + ModuleGroup moduleGroup = moduleGroupRepository.query(group.getId()); + if (null == moduleGroup) { + return new GeneralResult<>(false, "模型分组数据不存在"); + } + if (!moduleGroup.getName().equals(group.getName())) { + int sameName = moduleGroupRepository.countSameNameOrCode(group.getName(), null); + if (sameName > 0) { + return new GeneralResult<>(false, "更新失败,该名称已存在,请尝试其他名称"); + } + } + if (!moduleGroup.getCode().equals(group.getCode())) { + int sameCode = moduleGroupRepository.countSameNameOrCode(null, group.getCode()); + if (sameCode > 0) { + return new GeneralResult<>(false, "更新失败,该编码已存在,请尝试其他编码"); + } + } + if (!group.getParentId().equals(moduleGroup.getParentId())) { + List groups = moduleGroupRepository.queryChildren(group.getId()); + List modules = moduleRepository.queryByGroupId(group.getId()); + if (CollectionUtils.isNotEmpty(groups) || CollectionUtils.isNotEmpty(modules)) { + return new GeneralResult<>(false, "当前分组存在子数据,不可移动!"); + } + } + if (null == group.getParentId()) { + group.setParentId(0L); + } + BeanUtils.copyProperties(group, moduleGroup); + moduleGroup.setGmtModify(new Date()); + moduleGroup.setMenderId(target); + moduleGroupRepository.update(moduleGroup); + return new GeneralResult<>(true, "更新成功"); + } catch (Exception e) { + log.error("moduleGroupService modify fail:", e); + return new GeneralResult<>(false, "更新失败"); + } + } + + @Override + public GeneralResult queryChildren(Long groupId, String menu, RequestContext context) { + try { + // 获取模型分组所有数据 + List groups = moduleGroupRepository.all(); + ModuleGroup group = groups.stream().filter(item -> item.getId().equals(groupId)).findFirst().orElse(null); + if (null == group) { + return new GeneralResult<>(false, "不存在此分组!"); + } + // 对模型分组根据parentId进行分组 + Map> groupMap = + groups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + // 获取模型所有数据 + List modules = moduleRepository.all(); + if ("resource".equalsIgnoreCase(menu)) { + modules = modules.stream().filter(item -> ModuleConstant.STATUS_ENABLE.equals(item.getStatus())) + .collect(Collectors.toList()); + } + // 对模型根据groupId进行分组 + Map> moduleMap = modules.stream().collect(Collectors.groupingBy(CiModule::getGroupId)); + // 获取当前节点的子节点集合并判断子节点是否还包含数据 + List moduleGroups = groupMap.get(groupId); + if (CollectionUtils.isNotEmpty(moduleGroups)) { + for (ModuleGroup moduleGroup : moduleGroups) { + List childGroups = groupMap.get(moduleGroup.getId()); + List childModules = moduleMap.get(moduleGroup.getId()); + if (CollectionUtils.isEmpty(childGroups) && CollectionUtils.isEmpty(childModules)) { + moduleGroup.setExistNextData(false); + } else { + moduleGroup.setExistNextData(true); + } + } + } + // 当前节点的模型集合 + List childModules = moduleMap.get(groupId); + // 资源目录中查询模型对应的实例数量 + if ("resource".equalsIgnoreCase(menu)) { + if (CollectionUtils.isNotEmpty(childModules)) { + countModuleInstanceNum(childModules, context); + } + } + group.setChildrenGroups(moduleGroups); + group.setModules(childModules); + if (CollectionUtils.isEmpty(moduleGroups) && CollectionUtils.isEmpty(childModules)) { + group.setExistNextData(false); + } else { + group.setExistNextData(true); + } + return new GeneralResult<>(true, group, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService queryChildren fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void countModuleInstanceNum(List childModules, RequestContext context) { + + log.info("--------------start count instance num---------"); + try { + boolean hasAdminRole = instanceService.checkAdminRole(context.getTarget()); + List>> futureTasks = new ArrayList<>(); + for (CiModule module : childModules) { + FutureTask> task = + new FutureTask<>(new CountInstanceNumTask(module, context.getTarget(), hasAdminRole)); + futureTasks.add(task); + threadPoolTaskExecutor.submit(task); + } + Map resultMap = new HashMap<>(); + for (FutureTask> task : futureTasks) { + resultMap.putAll(task.get()); + } + for (CiModule module : childModules) { + module.setInstanceNum(resultMap.get(module.getId())); + } + } catch (Exception e) { + log.error("count instance num error", e); + } + log.info("--------------end count instance num---------"); + } + + private class CountInstanceNumTask implements Callable> { + + private CiModule module; + private Long userId; + private boolean hasAdminRole; + + public CountInstanceNumTask(CiModule module, Long userId, boolean hasAdminRole) { + this.module = module; + this.userId = userId; + this.hasAdminRole = hasAdminRole; + } + + @Override + public Map call() throws Exception { + Map map = new HashMap<>(); + map.put(module.getId(), countInstanceNum(module, userId, hasAdminRole)); + return map; + } + } + + private int countInstanceNum(CiModule module, Long userId, boolean hasAdminRole) { + int total = 0; + try { + String table = CmdbUtils.CMDB_INSTANCE + module.getCode().toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + List params = new ArrayList<>(); + Map newMap = new HashMap<>(); + newMap.put("moduleId", module.getId()); + Param param = new Param(); + param.setParam(newMap); + param.setSign(Sign.EQ); + params.add(param); + total = instanceRepository.count(params, table, valueTable, userId, hasAdminRole); + } catch (Exception e) { + log.error("查询模型实例数量出错", e); + } + return total; + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult remove(Long id, Long userId) { + String path = ModuleGroup.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + ModuleGroup moduleGroup = moduleGroupRepository.query(id); + if (null == moduleGroup) { + return new GeneralResult<>(false, "模型分组数据不存在"); + } + List groups = moduleGroupRepository.queryChildren(id); + if (!groups.isEmpty()) { + return new GeneralResult<>(false, "当前模型分组下存在子节点,拒绝删除"); + } + List modules = moduleRepository.queryByGroupId(id); + if (!modules.isEmpty()) { + return new GeneralResult<>(false, "当前模型分组下存在模型数据,拒绝删除"); + } + moduleGroupRepository.delete(id, userId); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("moduleGroupService remove fail:", e); + return new GeneralResult<>(false, "删除失败"); + } + } + + /** + * 新查询模型分组 + * + * @return 返回各分组中模型数量 + */ + @Override + public GeneralResult> querylist() { + try { + // 获取根数据 + List rootGroups = moduleGroupRepository.queryRoot(); + if (CollectionUtils.isEmpty(rootGroups)) { + return new GeneralResult<>(true, rootGroups, "查询成功"); + } + // 获取模型分组所有数据 + List moduleGroups = moduleGroupRepository.all(); + // 对模型分组根据parentId进行分组 + Map> groupMap = + moduleGroups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + List modules = moduleRepository.all(); + Map> moduleMap = modules.stream().collect(Collectors.groupingBy(CiModule::getGroupId)); + for (ModuleGroup group : rootGroups) { + this.getGroupTree(group, groupMap, moduleMap); + } + return new GeneralResult<>(true, rootGroups, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService queryRoot fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void getRootTree(List groups, Map> groupMap) { + for (ModuleGroup group : groups) { + List children = groupMap.get(group.getId()); + if (CollectionUtils.isEmpty(children)) { + continue; + } + group.setChildrenGroups(children); + this.getRootTree(children, groupMap); + } + } + + private void getGroupTree(ModuleGroup group, Map> groupMap, + Map> moduleMap) { + List children = groupMap.get(group.getId()); + if (CollectionUtils.isNotEmpty(children)) { + group.setChildrenGroups(children); + for (ModuleGroup child : children) { + this.getGroupTree(child, groupMap, moduleMap); + } + } + List modules = moduleMap.get(group.getId()); + int moduleCounts = 0; + if (CollectionUtils.isNotEmpty(modules)) { + moduleCounts = modules.size(); + } + int sum = 0; + if (CollectionUtils.isNotEmpty(group.getChildrenGroups())) { + for (ModuleGroup moduleGroup : group.getChildrenGroups()) { + sum = sum + moduleGroup.getCount(); + } + } + group.setCount(moduleCounts + sum); + ModuleGroup other = new ModuleGroup(); + other.setParentId(group.getId()); + other.setCode("!" + group.getCode() + group.getId()); + other.setName("其他"); + other.setCount(moduleCounts); + if (CollectionUtils.isNotEmpty(group.getChildrenGroups())) { + group.getChildrenGroups().add(other); + } else { + List list = new ArrayList<>(); + list.add(other); + group.setChildrenGroups(list); + } + } + + + @Override + public GeneralResult> queryRootChildren(Long groupId , String menu, RequestContext context) { + try { + List rootGroups = moduleGroupRepository.queryRoot(); + if (CollectionUtils.isEmpty(rootGroups)) { + return new GeneralResult<>(true, rootGroups, "查询成功"); + } + // 获取模型分组所有数据 + List groups = moduleGroupRepository.all(); + // 获取模型所有数据 + List modules = moduleRepository.all(); + // 对模型根据groupId进行分组 + Map> moduleMap = modules.stream().filter(item -> null != item.getGroupId()) + .collect(Collectors.groupingBy(CiModule::getGroupId)); + Map moduleGroupMap = groups.stream().collect(Collectors.toMap(ModuleGroup::getId, Function.identity())); + //获取groupId对应的所有父节点id + List parentIds = new ArrayList<>(); + getParentIds(parentIds, moduleGroupMap, groupId); + // 对模型分发根据parentId进行分组 + Map> moduleGroupListMap = groups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + // 获取模型所有数据 + if ("resource".equalsIgnoreCase(menu)) { + modules = modules.stream().filter(item -> ModuleConstant.STATUS_ENABLE.equals(item.getStatus())).collect(Collectors.toList()); + } + //当前模型分组及父分组下所有模型数据 + List newModules = modules.stream().filter(item -> parentIds.contains(item.getGroupId())).collect(Collectors.toList()); + //获取模型对应的实例数 + if ("resource".equalsIgnoreCase(menu)) { + if (CollectionUtils.isNotEmpty(newModules)) { + countModuleInstanceNum(newModules, context); + } + } + // 对模型根据groupId进行分组 + Map> newModuleMap = newModules.stream().collect(Collectors.groupingBy(CiModule::getGroupId)); + // 判断根节点是否包含子节点以及模型 + for (ModuleGroup moduleGroup : rootGroups) { + List childGroups = moduleGroupListMap.get(moduleGroup.getId()); + List childMudules = moduleMap.get(moduleGroup.getId()); + if (CollectionUtils.isEmpty(childGroups) && CollectionUtils.isEmpty(childMudules)) { + moduleGroup.setExistNextData(false); + } else { + moduleGroup.setExistNextData(true); + } + if (parentIds.contains(moduleGroup.getId())) { + //moduleGroup 初始化模型及子分组 + dealModuleGroup(parentIds, moduleGroup, moduleMap, newModuleMap, moduleGroupListMap); + } + } + return new GeneralResult<>(true, rootGroups, "查询成功"); + } catch (Exception e) { + log.error("moduleGroupService queryChildren fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void dealModuleGroup(List parentIds, ModuleGroup moduleGroup, Map> moduleMap, Map> newModuleMap, Map> moduleGroupListMap) { + List listModule = moduleMap.get(moduleGroup.getId()); + List listGroup = moduleGroupListMap.get(moduleGroup.getId()); + if (CollectionUtils.isEmpty(listModule) && CollectionUtils.isEmpty(listGroup)) { + moduleGroup.setExistNextData(false); + } else { + moduleGroup.setExistNextData(true); + } + if (parentIds.contains(moduleGroup.getId())) { + moduleGroup.setModules(newModuleMap.get(moduleGroup.getId())); + moduleGroup.setChildrenGroups(listGroup); + if (CollectionUtils.isEmpty(listGroup)) { + return; + } + for (ModuleGroup group : listGroup) { + dealModuleGroup(parentIds, group, moduleMap, newModuleMap, moduleGroupListMap); + } + } + } + + //获取当前节点及其所有父节点的id + private void getParentIds(List ids, Map moduleGroupMap, Long groupId) { + ids.add(0, groupId); + ModuleGroup group = moduleGroupMap.get(groupId); + if (group.getParentId() == 0) { + return; + } + getParentIds(ids, moduleGroupMap, group.getParentId()); + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleRelationServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleRelationServiceImpl.java new file mode 100644 index 0000000..e508869 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleRelationServiceImpl.java @@ -0,0 +1,592 @@ +package com.bocloud.ams.service.module.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.model.ModuleLink; +import com.bocloud.ams.entity.model.ModuleTopo; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.Relation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.repository.association.AutoRelationRuleItemRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleItemValueRepository; +import com.bocloud.ams.repository.association.AutoRelationRuleRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.RelationCategoryRepository; +import com.bocloud.ams.repository.module.RelationRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceService; +import com.bocloud.ams.service.module.ModuleRelationService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Description: 模型关系管理 + * @Title: CmdbRelationService + * @Author: majiali + * @CreateTime: 2022/5/7 16:59 + */ +@Slf4j +@Service("moduleRelationService") +public class ModuleRelationServiceImpl implements ModuleRelationService { + + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private RelationRepository relationRepository; + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private AutoRelationRuleRepository autoRelationRuleRepository; + @Autowired + private AutoRelationRuleItemRepository autoRelationRuleItemRepository; + @Autowired + private AutoRelationRuleItemValueRepository autoRelationRuleItemValueRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceService instanceService; + + @Override + public GeneralResult create(ModuleRelation relation, Long userId) { + try { + Long sourceId = relation.getSourceId(); + Long targetId = relation.getTargetId(); + Long relationId = relation.getRelationId(); + CiModule sourceModule = moduleRepository.query(sourceId); + if (null == sourceModule) { + return new GeneralResult<>(false, "源模型不存在"); + } + CiModule targetModule = moduleRepository.query(targetId); + if (null == targetModule) { + return new GeneralResult<>(false, "目的模型不存在"); + } + if (sourceId.equals(targetId)) { + return new GeneralResult<>(false, "源模型和目的模型不能为同一个模型"); + } + RelationCategory relationCategory = relationCategoryRepository.query(relation.getRelationCategoryId()); + if (null == relationCategory) { + return new GeneralResult<>(false, "关联类型分组不存在"); + } + Relation cmdbRelation = relationRepository.query(relationId); + if (null == cmdbRelation) { + return new GeneralResult<>(false, "关联类型不存在"); + } + // 正向规则 + ModuleRelation moduleRelation = + moduleRelationRepository.query(relation.getRelationCategoryId(), sourceId, targetId); + if (null != moduleRelation) { + return new GeneralResult<>(false, "模型关系已经存在"); + } + // 反向规则校验 + ModuleRelation everseRelation = + moduleRelationRepository.query(relation.getRelationCategoryId(), targetId, sourceId); + if (null != everseRelation) { + return new GeneralResult<>(false, "模型关系已经存在"); + } + relation.setSourceCode(sourceModule.getCode()); + relation.setTargetCode(targetModule.getCode()); + relation.setRelationCategoryCode(relationCategory.getCode()); + relation.setDeleted(false); + relation.setCreatorId(userId); + relation.setMenderId(userId); + relation.setGmtModify(new Date()); + relation.setGmtCreate(new Date()); + relation.setName(sourceModule.getName() + cmdbRelation.getName() + targetModule.getName()); + moduleRelationRepository.save(relation); + List item = relation.getRuleItemList(); + if (!CollectionUtils.isEmpty(item)) { + AutoRelationRule rule = new AutoRelationRule(); + rule.setName(sourceModule.getName() + cmdbRelation.getName() + targetModule.getName()); + rule.setItems(item); + rule.setSourceModuleId(sourceId); + rule.setTargetModuleId(targetId); + rule.setRelationCategoryId(relation.getRelationCategoryId()); + rule.setModuleRelationId(relation.getId()); + saveRelationRule(rule, userId); + } + return new GeneralResult<>(true, "模型关系新增成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation create fail:", e); + return new GeneralResult<>(false, "模型关系新增失败"); + } + } + + private void saveRelationRule(AutoRelationRule rule, Long target) { + if (CollectionUtils.isEmpty(rule.getItems())) { + return; + } + rule.setCreatorId(target); + rule.setGmtCreate(new Date()); + rule.setDeleted(false); + autoRelationRuleRepository.save(rule); + rule.getItems().forEach(item -> { + item.setRelationRuleId(rule.getId()); + item.setCreatorId(target); + item.setGmtCreate(new Date()); + item.setDeleted(false); + autoRelationRuleItemRepository.save(item); + List itemValues = item.getValues(); + if (!CollectionUtils.isEmpty(itemValues)) { + itemValues.forEach(value -> { + value.setRelationRuleId(rule.getId()); + value.setItemId(item.getId()); + value.setCreatorId(target); + value.setGmtCreate(new Date()); + item.setDeleted(false); + autoRelationRuleItemValueRepository.save(value); + }); + } + }); + } + + @Override + public GeneralResult modify(ModuleRelation relation, Long userId) { + String path = ModuleRelationServiceImpl.class.getSimpleName() + "_" + relation.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CiModule sourceModule = moduleRepository.query(relation.getSourceId()); + if (null == sourceModule) { + return new GeneralResult<>(false, "源模型不存在"); + } + CiModule targetModule = moduleRepository.query(relation.getTargetId()); + if (null == targetModule) { + return new GeneralResult<>(false, "目的模型不存在"); + } + if (relation.getSourceId().equals(relation.getTargetId())) { + return new GeneralResult<>(false, "源模型和目的模型不能为同一个模型"); + } + RelationCategory relationCategory = relationCategoryRepository.query(relation.getRelationCategoryId()); + if (null == relationCategory) { + return new GeneralResult<>(false, "关联类型分组不存在"); + } + Relation cmdbRelation = relationRepository.query(relation.getRelationId()); + if (null == cmdbRelation) { + return new GeneralResult<>(false, "关联类型不存在"); + } + ModuleRelation temp = moduleRelationRepository.query(relation.getId()); + if (null == temp) { + return new GeneralResult<>(false, "模型关系不存在"); + } + LocaleBeanUtils.copyProperties(temp, relation); + temp.setName(sourceModule.getName() + cmdbRelation.getName() + targetModule.getName()); + temp.setGmtModify(new Date()); + temp.setMenderId(userId); + moduleRelationRepository.update(temp); + // 查询规则 + AutoRelationRule rule = autoRelationRuleRepository.queryByModuleRelationId(temp.getId()); + if (null == rule) { + rule = new AutoRelationRule(); + rule.setName(temp.getName()); + rule.setItems(relation.getRuleItemList()); + rule.setSourceModuleId(temp.getSourceId()); + rule.setTargetModuleId(temp.getTargetId()); + rule.setRelationCategoryId(temp.getRelationCategoryId()); + rule.setModuleRelationId(temp.getId()); + rule.setItems(relation.getRuleItemList()); + saveRelationRule(rule, userId); + } else { + rule.setItems(relation.getRuleItemList()); + modifyRelationRule(rule, userId); + } + return new GeneralResult<>(true, "模型关系修改成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation modify fail:", e); + return new GeneralResult<>(false, "模型关系修改失败"); + } + } + + private void modifyRelationRule(AutoRelationRule rule, Long target) throws Exception { + // 更新规则明细数据 + autoRelationRuleItemRepository.deleteByRuleId(rule.getId(), target); + autoRelationRuleItemValueRepository.deleteByRuleId(rule.getId(), target); + if (CollectionUtils.isEmpty(rule.getItems())) { + autoRelationRuleRepository.delete(rule.getId(), target); + return; + } + // 更新模型关系规则 + rule.setGmtModify(new Date()); + rule.setMenderId(target); + autoRelationRuleRepository.update(rule); + rule.getItems().forEach(item -> { + item.setRelationRuleId(rule.getId()); + item.setId(null); + item.setCreatorId(target); + item.setGmtCreate(new Date()); + autoRelationRuleItemRepository.save(item); + List itemValues = item.getValues(); + if (!CollectionUtils.isEmpty(itemValues)) { + itemValues.forEach(value -> { + value.setRelationRuleId(rule.getId()); + value.setId(null); + value.setItemId(item.getId()); + value.setCreatorId(target); + value.setGmtCreate(new Date()); + autoRelationRuleItemValueRepository.save(value); + }); + } + }); + } + + @Override + public GeneralResult detail(Long id) { + try { + ModuleRelation relation = moduleRelationRepository.query(id); + if (null == relation) { + return new GeneralResult<>(false, "模型关系查询失败,数据不存在"); + } + // 查询关联规则信息 + AutoRelationRule rule = autoRelationRuleRepository.queryByModuleRelationId(id); + if (null != rule) { + List items = autoRelationRuleItemRepository.queryByRuleId(rule.getId()); + for (AutoRelationRuleItem item : items) { + item.setValues(autoRelationRuleItemValueRepository.queryByItemId(item.getId())); + } + relation.setRuleItemList(items); + } + return new GeneralResult<>(true, relation, "模型关系查询成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation detail query fail:", e); + return new GeneralResult<>(false, "模型关系查询失败"); + } + } + + @Override + public GeneralResult remove(Long id, Long userId) { + String path = ModuleRelationServiceImpl.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + ModuleRelation temp = moduleRelationRepository.query(id); + if (null == temp) { + return new GeneralResult<>(false, "模型关系不存在"); + } + // 查询实例关系 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + temp.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List relations = instanceRelationRepository.queryByCondition(instanceRelationTable, + temp.getSourceId(), null, temp.getTargetId(), null); + if (CollectionUtils.isNotEmpty(relations)) { + return new GeneralResult<>(false, "当前模型关系下存在对应的实例关系,请先删除实例关系"); + } + // 级联删除规则相关信息 + AutoRelationRule relationRule = autoRelationRuleRepository.queryByModuleRelationId(id); + if (null != relationRule) { + autoRelationRuleItemValueRepository.deleteByRuleId(relationRule.getId(), userId); + autoRelationRuleItemRepository.deleteByRuleId(relationRule.getId(), userId); + autoRelationRuleRepository.delete(relationRule.getId(), userId); + } + moduleRelationRepository.delete(id, userId); + return new GeneralResult<>(true, "模型关系删除成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation remove fail:", e); + return new GeneralResult<>(false, "模型关系删除失败"); + } + } + + @Override + public GeneralResult list(Long moduleId, Long relationCategoryId) { + try { + if (null == moduleId || null == relationCategoryId) { + return GeneralResult.FAILED("模型id或拓扑id不可为空"); + } + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return GeneralResult.FAILED("该模型不存在"); + } + RelationCategory category = relationCategoryRepository.query(relationCategoryId); + if (null == category) { + return GeneralResult.FAILED("该拓扑不存在"); + } + // 正向关系 + List relations = moduleRelationRepository.list(moduleId, relationCategoryId); + // 反向关系isReverse + List reverseRelations = moduleRelationRepository.listReverse(moduleId, relationCategoryId); + relations.addAll(reverseRelations); + // 所有模型ids + Set moduleSet = new HashSet<>(); + // 放入自身 + moduleSet.add(module.getId()); + List links = new ArrayList<>(); + for (ModuleRelation relation : relations) { + moduleSet.add(relation.getSourceId()); + moduleSet.add(relation.getTargetId()); + // 放入link + ModuleLink link = new ModuleLink(); + link.setRelationId(relation.getId()); + link.setRelationCategoryId(relation.getRelationCategoryId()); + link.setRelationCode(relation.getRelationCode()); + link.setRelationName(relation.getRelationName()); + link.setIsReversed(relation.getIsReversed()); + // 反向的时候,箭头相反相关信息 + if (relation.getIsReversed()) { + link.setSource(relation.getTargetId()); + link.setTarget(relation.getSourceId()); + link.setType(relation.getTargetType() + "-" + relation.getSourceType()); + } else { + link.setSource(relation.getSourceId()); + link.setTarget(relation.getTargetId()); + link.setType(relation.getSourceType() + "-" + relation.getTargetType()); + } + links.add(link); + } + List nodes = new ArrayList<>(); + if (moduleSet.size() > 0) { + List ids = new ArrayList<>(); + ids.addAll(moduleSet); + nodes = moduleRepository.listByIds(ids); + } + ModuleTopo topo = new ModuleTopo(nodes, links); + return new GeneralResult<>(true, topo, "查询模型关系成功!"); + } catch (Exception e) { + log.error("CmdbModuleRelation list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult listByCategoryId(Long relationCategoryId) { + try { + if (null == relationCategoryId) { + return GeneralResult.FAILED("拓扑id不可为空"); + } + RelationCategory relationCategory = relationCategoryRepository.query(relationCategoryId); + if (null == relationCategory) { + return GeneralResult.FAILED("该拓扑不存在"); + } + // 正向找关系 + List relations = moduleRelationRepository.listByCategoryId(relationCategoryId); + // 所有模型ids + Set moduleSet = new HashSet<>(); + List links = new ArrayList<>(); + for (ModuleRelation relation : relations) { + moduleSet.add(relation.getSourceId()); + moduleSet.add(relation.getTargetId()); + // 放入link + ModuleLink link = new ModuleLink(); + link.setRelationId(relation.getId()); + link.setRelationCategoryId(relation.getRelationCategoryId()); + link.setRelationCode(relation.getRelationCode()); + link.setRelationName(relation.getRelationName()); + link.setSource(relation.getSourceId()); + link.setTarget(relation.getTargetId()); + link.setType(relation.getSourceType() + "-" + relation.getTargetType()); + links.add(link); + } + List nodes = new ArrayList<>(); + if (moduleSet.size() > 0) { + List ids = new ArrayList<>(); + ids.addAll(moduleSet); + nodes = moduleRepository.listByIds(ids); + } + // 处理nodes和links + ModuleTopo topo = new ModuleTopo(nodes, links); + return new GeneralResult<>(true, topo, "查询模型关系成功!"); + } catch (Exception e) { + log.error("CmdbModuleRelation list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult relevancy(Long relationCategoryId, Long sourceId, Long targetId) { + try { + if (null == relationCategoryId) { + return new GeneralResult<>(false, "缺少拓扑参数"); + } + if (null == sourceId) { + return new GeneralResult<>(false, "缺少源模型参数"); + } + if (null == targetId) { + return new GeneralResult<>(false, "缺少目标模型参数"); + } + ModuleRelation relation = moduleRelationRepository.query(relationCategoryId, sourceId, targetId); + if (null != relation) { + // 查询关联规则信息 + AutoRelationRule rule = autoRelationRuleRepository.queryByModuleRelationId(relation.getId()); + if (null != rule) { + List items = autoRelationRuleItemRepository.queryByRuleId(rule.getId()); + for (AutoRelationRuleItem item : items) { + item.setValues(autoRelationRuleItemValueRepository.queryByItemId(item.getId())); + } + relation.setRuleItemList(items); + } + } + return new GeneralResult<>(true, relation, "查询成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation data query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 关联类型分组id查询模型集合 + * + * @param relationCategoryId + * @return + */ + @Override + public GeneralResult> moduleList(Long relationCategoryId) { + try { + List relations = moduleRelationRepository.queryModuleList(relationCategoryId); + if (CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(true, new ArrayList(), "查询成功"); + } + List sourceIds = relations.stream().map(ModuleRelation::getSourceId).collect(Collectors.toList()); + List targetIds = relations.stream().map(ModuleRelation::getTargetId).collect(Collectors.toList()); + // 去重取 + List moduleIds = Stream.of(sourceIds, targetIds).flatMap(Collection::stream).filter(Objects::nonNull) + .distinct().collect(Collectors.toList()); + // 获取模型集合 + List modules = moduleRepository.queryModuleListByIds(moduleIds); + return new GeneralResult<>(true, modules, "查询成功"); + } catch (Exception e) { + log.error("CmdbModuleRelation modules query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult instances(Pager pager, Long userId) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + pager.getSorter().put("id", Common.ONE); + Long id = null; + Long moduleId = null; + Long instanceId = null; + // 实例属性条件查询 + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("id")) { + if (!StringUtils.isEmpty(paramMap.get("id").toString())) { + id = Long.valueOf(paramMap.get("id").toString()); + } + paramMap.remove("id"); + } + if (paramMap.containsKey("moduleId")) { + if (!StringUtils.isEmpty(paramMap.get("moduleId").toString())) { + moduleId = Long.valueOf(paramMap.get("moduleId").toString()); + } + } + if (paramMap.containsKey("instanceId")) { + if (!StringUtils.isEmpty(paramMap.get("instanceId").toString())) { + instanceId = Long.valueOf(paramMap.get("instanceId").toString()); + } + paramMap.remove("instanceId"); + } + } + ModuleRelation moduleRelation = moduleRelationRepository.query(id); + if (null == moduleRelation) { + return GeneralResult.FAILED("模型关系不存在"); + } + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return GeneralResult.FAILED("模型不存在"); + } + // 被关联的模型 + String finalModuleCode = null; + Long finalModuleId = null; + // 实例类型:目标实例、源实例 + String finalInstanceType = null; + // 取非当前moduleId对应模型的模型,即若moduleId为源,则查询目标; + if (moduleId.equals(moduleRelation.getSourceId())) { + finalModuleCode = moduleRelation.getTargetCode(); + finalModuleId = moduleRelation.getTargetId(); + finalInstanceType = CmdbUtils.INSTANCE_RELATION_TYPE_TARGET; + } else if (moduleId.equals(moduleRelation.getTargetId())) { + finalModuleCode = moduleRelation.getSourceCode(); + finalModuleId = moduleRelation.getSourceId(); + finalInstanceType = CmdbUtils.INSTANCE_RELATION_TYPE_SOURCE; + } + + if (StringUtils.isEmpty(finalModuleCode) || null == finalModuleId + || StringUtils.isEmpty(moduleRelation.getRelationCategoryCode())) { + return GeneralResult.FAILED("模型关系不完整"); + } + // 查询目标模型的实例数据 + for (Param param : pager.getParams()) { + Map paramMap = param.getParam(); + if (paramMap.containsKey("moduleId")) { + paramMap.put("moduleId", finalModuleId); + } + } + String instanceTable = CmdbUtils.CMDB_INSTANCE + finalModuleCode.toLowerCase(); + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + finalModuleCode.toLowerCase(); + String relationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询已关联实例 + List relations = null; + Map relationMap = new HashMap<>(); + if (CmdbUtils.INSTANCE_RELATION_TYPE_SOURCE.equals(finalInstanceType)) { + relations = instanceRelationRepository.query(relationTable, finalModuleId, null, moduleId, instanceId); + for (InstanceRelation relation : relations) { + relationMap.put(relation.getSourceInstanceId(), relation); + } + } else if (CmdbUtils.INSTANCE_RELATION_TYPE_TARGET.equals(finalInstanceType)) { + relations = instanceRelationRepository.query(relationTable, moduleId, instanceId, finalModuleId, null); + for (InstanceRelation relation : relations) { + relationMap.put(relation.getTargetInstanceId(), relation); + } + } + + boolean hasAdminRole = instanceService.checkAdminRole(userId); + // 查询可被关联的模型实例 + List> list = + instanceRepository.list(pager, instanceTable, valueTable, userId, hasAdminRole); + int total = instanceRepository.count(pager.getParams(), instanceTable, valueTable, userId, hasAdminRole); + instanceService.convertInstanceValue(list, moduleId, userId, hasAdminRole); + for (Map instance : list) { + // 判断被关联的模型实例是否已关联 + InstanceRelation existRelation = relationMap.get(instance.get("id")); + instance.put("isRelation", null != existRelation); + instance.put("instanceRelation", existRelation);// 存放关联实例的关联关系,配合isRelation一起使用,取消关联需要这个关系的ID + } + GridBean> bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + return new GeneralResult<>(false, "查询模型实例失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleServiceImpl.java new file mode 100644 index 0000000..6b92ff2 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/ModuleServiceImpl.java @@ -0,0 +1,773 @@ +package com.bocloud.ams.service.module.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.BeanUtilsBean; +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; +import org.springframework.util.Assert; + +import com.alibaba.fastjson.JSON; +import com.bocloud.ams.entity.collection.CollectionComponent; +import com.bocloud.ams.entity.enums.PropertyType; +import com.bocloud.ams.entity.model.PropertyModel; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleGroup; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyGroup; +import com.bocloud.ams.entity.module.PropertyItem; +import com.bocloud.ams.entity.module.PropertyPool; +import com.bocloud.ams.entity.module.TopologyConfig; +import com.bocloud.ams.repository.collection.CollectionComponentRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleGroupRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.PropertyGroupRepository; +import com.bocloud.ams.repository.module.PropertyItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.module.RegularExpressionRepository; +import com.bocloud.ams.repository.module.TopologyConfigRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceService; +import com.bocloud.ams.service.module.ModuleService; +import com.bocloud.ams.service.module.PropertyService; +import com.bocloud.ams.service.utils.ModuleConstant; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.google.common.collect.Lists; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.RequestContext; +import com.megatron.common.model.Sign; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.ListTool; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/5 11:55 + */ +@Service +@Slf4j +public class ModuleServiceImpl implements ModuleService { + + @Autowired + private LockFactory lockFactory; + @Autowired + PropertyRepository propertyRepository; + @Autowired + PropertyGroupRepository propertyGroupRepository; + @Autowired + PropertyItemRepository propertyItemRepository; + @Autowired + RegularExpressionRepository regularExpressionRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private InstanceService instanceService; + @Autowired + private PropertyPoolRepository propertyPoolRepository; + @Autowired + private PropertyService propertyService; + @Autowired + private TopologyConfigRepository topologyConfigRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private CollectionComponentRepository collectionComponentRepository; + @Autowired + private ModuleGroupRepository moduleGroupRepository; + + @Override + public GeneralResult> getModelList(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + // flag = false 仅查询当前分组下的模型数据;flag = true 查询当前分组下的所有模型数据包括子分组的模型数据 + List params = pager.getParams(); + List> collectMap = params.stream().map(Param::getParam).collect(Collectors.toList()); + Map map = + collectMap.stream().filter(item -> item.containsKey("flag")).findFirst().orElse(null); + if (null != map) { + Param newParam = null; + Iterator iterator = params.iterator(); + while (iterator.hasNext()) { + Map parMap = iterator.next().getParam(); + if (parMap.containsKey("moduleGroupId") && parMap.containsKey("flag")) { + Long groupId = Long.valueOf((Integer)parMap.get("moduleGroupId")); + if (parMap.get("flag").equals(true)) { + // 递归获取所有子groupId + List groups = moduleGroupRepository.all(); + Map> groupMap = + groups.stream().collect(Collectors.groupingBy(ModuleGroup::getParentId)); + List groupIds = new ArrayList<>(); + this.getGroups(groupIds, groupId, groupMap); + List groupIdList = + groupIds.stream().map(String::valueOf).collect(Collectors.toList()); + String ids = String.join(",", groupIdList); + Map groupIdMap = new HashMap<>(); + groupIdMap.put("moduleGroupId", ids); + newParam = new Param(groupIdMap, Sign.IN); + } else { + Map groupIdMap = new HashMap<>(); + groupIdMap.put("moduleGroupId", groupId); + newParam = new Param(groupIdMap, Sign.EQ); + } + iterator.remove(); + break; + } + } + if (null != newParam) { + params.add(newParam); + } + } + int total = moduleRepository.count(pager.getParams()); + List modules = this.moduleRepository.list(pager); + if (CollectionUtils.isNotEmpty(modules)) { + List groupIds = modules.stream().map(CiModule::getGroupId).collect(Collectors.toList()); + List groups = moduleGroupRepository.queryByIds(groupIds); + if (CollectionUtils.isNotEmpty(groups)) { + for (CiModule module : modules) { + ModuleGroup group = groups.stream().filter(item -> item.getId().equals(module.getGroupId())) + .findFirst().orElse(null); + if (null != group) { + module.setParentGroupId(group.getParentId()); + } + } + } + } + GridBean bean = new GridBean<>(pager.getPage(), pager.getRows(), total, modules); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> list() { + try { + List modules = moduleRepository.all(); + List list = modules.stream().filter(item -> ModuleConstant.STATUS_ENABLE.equals(item.getStatus())) + .collect(Collectors.toList()); + return new GeneralResult<>(true, list, "查询成功!"); + } catch (Exception e) { + log.error("query module is error:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + CiModule module = moduleRepository.query(id); + return new GeneralResult<>(true, module, "查询成功"); + } catch (Exception e) { + log.error("moduleService detail fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult save(CiModule module, Long target) { + try { + int sameName = moduleRepository.countSameNameOrCode(module.getName(), null); + if (sameName > 0) { + return new GeneralResult<>(false, "添加失败,该名称已存在,请尝试其他名称"); + } + int sameCode = moduleRepository.countSameNameOrCode(null, module.getCode()); + if (sameCode > 0) { + return new GeneralResult<>(false, "添加失败,该编码已存在,请尝试其他编码"); + } + if (null == module.getGroupId()) { + return new GeneralResult<>(false, "模型要有对应分组!"); + } + String instanceTable = CmdbUtils.CMDB_INSTANCE + module.getCode().toLowerCase(); + if (instanceRepository.countTable(instanceTable) > 0) { + log.warn("创建表空间{}失败", instanceTable); + return new GeneralResult<>(false, "创建失败," + instanceTable + "实例表已存"); + } + String valueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + if (instanceValueRepository.countTable(valueTable) > 0) { + log.warn("创建表空间{}失败", valueTable); + return new GeneralResult<>(false, "创建失败," + valueTable + "实例表已存"); + } + if (null == module.getStatus()) { + module.setStatus(ModuleConstant.STATUS_ENABLE); + } + module.setGmtCreate(new Date()); + module.setGmtModify(new Date()); + module.setCreatorId(target); + module.setMenderId(target); + module.setReserved(false); + moduleRepository.save(module); + // 新增初始化数据property + if (null == module.getId()) { + log.warn("Create notice module fail!"); + return new GeneralResult<>(false, "新增模型失败"); + } + List properties = Lists.newArrayList(); + PropertyGroup group = new PropertyGroup(); + group.setName("基础属性"); + group.setIsReserved(true); + group.setModuleId(module.getId()); + group.setOrderNum(0); + group.setCreatorId(target); + group.setMenderId(target); + propertyGroupRepository.save(group); + if (null == group.getId()) { + log.warn("Create PropertyGroup fail!"); + return new GeneralResult<>(false, "新增模型属性分组失败"); + } + Property id = new Property("uuid", "唯一标识", PropertyType.TEXTFIELD.name(), group.getName(), 100, true, true, + 1, module.getId(), true, false, false, target, PropertyConstant.DefaultValueType.INNERFUN, + PropertyConstant.GLOBALLY_UNIQUE_IDENTIFIER, true, false); + // name设置为标题列 + Property name = new Property("name", "名称", PropertyType.TEXTFIELD.name(), group.getName(), 100, true, true, + 2, module.getId(), true, false, true, target, PropertyConstant.DefaultValueType.FIXED, null, false, + true); + properties.add(id); + properties.add(name); + propertyRepository.batchSave(properties, 10); + // 创建模型对应的实例表 + instanceService.createTable(module.getCode(), target); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("moduleService save fail:", e); + // 手动事务回滚 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult modify(CiModule module, Long target) { + String path = CiModule.class.getSimpleName() + "_" + module.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CiModule object = moduleRepository.query(module.getId()); + if (null == object) { + return new GeneralResult<>(false, "模型数据不存在"); + } + if (!object.getName().equals(module.getName())) { + int sameName = moduleRepository.countSameNameOrCode(module.getName(), null); + if (sameName > 0) { + return new GeneralResult<>(false, "修改失败,该名称已存在,请尝试其他名称"); + } + } + if (!object.getCode().equals(module.getCode())) { + int sameCode = moduleRepository.countSameNameOrCode(null, module.getCode()); + if (sameCode > 0) { + return new GeneralResult<>(false, "修改失败,该编码已存在,请尝试其他编码"); + } + } + LocaleBeanUtils.copyProperties(object, module); + if (null == object.getStatus()) { + object.setStatus(ModuleConstant.STATUS_ENABLE); + } + object.setGmtModify(new Date()); + object.setMenderId(target); + moduleRepository.update(object); + return new GeneralResult<>(true, "变更成功"); + } catch (Exception e) { + log.error("moduleService modify fail:", e); + // 手动事务回滚 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return new GeneralResult<>(false, "变更成功"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public GeneralResult remove(Long id, Long userId) { + String path = CiModule.class.getSimpleName() + "_sasasas" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + CiModule module = moduleRepository.query(id); + if (null == module) { + return new GeneralResult<>(false, "模型数据不存在"); + } + List configs = topologyConfigRepository.listAll(); + // 获取拓扑路径涉及到的模型数据 + List modules = configs.stream().filter(item -> StringUtils.isNotEmpty(item.getTopologyPath())) + .flatMap(config -> Arrays.stream(config.getTopologyPath().split(","))).distinct() + .map(item -> Long.valueOf(item)).collect(Collectors.toList()); + List ignores = configs.stream().filter(item -> StringUtils.isNotEmpty(item.getIgnoreModuleIds())) + .flatMap(config -> Arrays.stream(config.getIgnoreModuleIds().split(","))).distinct() + .map(item -> Long.valueOf(item)).collect(Collectors.toList()); + modules.addAll(ignores); + modules.removeAll(Collections.singleton(null)); // 移除所有的null元素 + if (modules.contains(id)) { + return new GeneralResult<>(false, "实例拓扑中使用到此模型,删除失败!"); + } + // 校验是否被其他模型属性引用(多行表格和单行表格存在引入其他模型属性) + List linkModules = propertyRepository.queryByLinkModuleId(id); + if (CollectionUtils.isNotEmpty(linkModules)) { + return new GeneralResult<>(false, "存在其他模型引用此模型属性,模型删除失败!"); + } + List collectionComponents = collectionComponentRepository.queryByModuleId(id); + if (CollectionUtils.isNotEmpty(collectionComponents)) { + return new GeneralResult<>(false, "当前模型已被采集插件使用,模型删除失败!"); + } + // 删除模型数据 + moduleRepository.delete(id, userId); + // 删除模型属性 + propertyRepository.deleteByModuleId(id, userId); + // 删除模型属性分组 + propertyGroupRepository.deleteByModuleId(id, userId); + // 删除模型属性明细数据 + propertyItemRepository.deleteByModuleId(id, userId); + // 删除模型的关联关系 + moduleRelationRepository.deleteByModuleId(id, userId); + // 删除模型实例表 + instanceService.dropTable(module.getCode(), userId); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("moduleService remove fail:", e); + // 手动事务回滚 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return new GeneralResult<>(false, "删除失败"); + } + } + + @Override + public GeneralResult property(Long moduleId) { + try { + List groups = propertyGroupRepository.listByModuleId(moduleId); + List properties = propertyRepository.listNotHiddenByCmdbModuleId(moduleId); + List items = propertyItemRepository.queryByModuleId(moduleId); + for (Property property : properties) { + propertyService.propertyHandle(property, items); + } + PropertyModel model = new PropertyModel(moduleId, groups, properties); + return new GeneralResult<>(true, model, "查询属性成功"); + } catch (Exception e) { + log.error("moduleService property fail:", e); + return new GeneralResult<>(false, "查询属性失败"); + } + } + + @Override + public GeneralResult> propertyList(Long moduleId, Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put("id", Common.ONE); + int total = propertyRepository.count(pager.getParams(), moduleId); + List properties = propertyRepository.list(pager, moduleId); + for (Property property : properties) { + if (null != property.getPropertyPoolId()) { + PropertyPool pool = propertyPoolRepository.query(property.getPropertyPoolId()); + this.copyProperties(property, pool); + } + property.setPropertyId(property.getId()); + } + GridBean bean = new GridBean<>(pager.getPage(), pager.getRows(), total, properties); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("moduleService propertyList fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + @Transactional(rollbackFor = {Exception.class}) + public GeneralResult modifyProperty(PropertyModel model, Long id, RequestContext context) { + String path = Property.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + // 数据处理 + return this.baseModifyProperty(id, model.getGroups(), model.getProperties(), context.getTarget()); + } catch (Exception e) { + log.error("moduleService modifyProperty fail:", e); + // 手动事务回滚 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return new GeneralResult<>(false, "保存失败," + e.getMessage()); + } + } + + private GeneralResult baseModifyProperty(Long moduleId, List groups, List properties, + Long userId) throws Exception { + CiModule module = moduleRepository.query(moduleId); + if (module == null) { + return GeneralResult.FAILED("修改属性对应的配置模型不存在"); + } + // 参数的数据校验 + this.validate(properties, groups); + // 查询原本的property数据 + List oldProperties = propertyRepository.listNotHiddenByCmdbModuleId(moduleId); + // 查询原本的propertyItem数据 + List oldItems = propertyItemRepository.queryByModuleId(moduleId); + // 查询原本的group数据 + List oldGroups = propertyGroupRepository.listByModuleId(moduleId); + // 1-add:新增property数据 以及对应的propertyItem数据 + List addProperties = + properties.stream().filter(item -> null == item.getId()).collect(Collectors.toList()); + // 3-update:更新property数据(不允许从池表中引入的数据被更新) 以及对应的propertyItem数据 + List updateProperties = properties.stream() + .filter(item -> null != item.getId()).collect(Collectors.toList()); + // 2-delete:删除去掉的property数据 以及对应的propertyItem数据 + List inputPropertyIds = + properties.stream().filter(item -> null != item.getId()).map(Property::getId).collect(Collectors.toList()); + List deleteProperties = oldProperties.stream() + .filter(item -> !inputPropertyIds.contains(item.getId())).collect(Collectors.toList()); + // 1-delete:删除去掉的property数据 以及 对应的propertyItem数据 + if (CollectionUtils.isNotEmpty(deleteProperties)) { + // 先校验是否存在被其他模型引用的属性,如果存在就不允许删除 + List deletePropertyIds = deleteProperties.stream().map(Property::getId).collect(Collectors.toList()); + List linkModuleIds = propertyRepository.queryByLinkModuleId(moduleId); + if (CollectionUtils.isNotEmpty(linkModuleIds)) { + long count = linkModuleIds.stream().map(Property::getPropertyIds).map(item -> item.split(",")) + .flatMap(item -> Arrays.stream(item)).filter(item -> deletePropertyIds.contains(item)).count(); + if (count > 0) { + return GeneralResult.FAILED("删除属性失败,存在其他模型引用此属性"); + } + } + // 校验当前模型属性是否被采集插件引用 + List collectionComponents = collectionComponentRepository.queryByModuleId(moduleId); + if (CollectionUtils.isNotEmpty(collectionComponents)) { + long count = collectionComponents.stream().map(CollectionComponent::getPropertyId) + .filter(item -> deletePropertyIds.contains(item)).count(); + if (count > 0) { + return GeneralResult.FAILED("删除属性失败,存在属性被采集插件使用"); + } + } + deleteProperties.stream().forEach(item -> { + item.setGmtModify(new Date()); + item.setMenderId(userId); + item.setDeleted(true); + }); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + for (Property deleteProperty : deleteProperties) { + propertyRepository.update(deleteProperty); + // 删除对应的实例数据 + instanceValueRepository.removeByPropertyId(deleteProperty.getId(), instanceValueTable, userId); + } + // propertyRepository.batchUpdate(deleteProperties, deleteProperties.size()); + // 根据需要删除的property数据删除对应的propertyItem数据 + List propertyIds = deleteProperties.stream().map(Property::getId).collect(Collectors.toList()); + List deleteItems = oldItems.stream() + .filter(item -> propertyIds.contains(item.getPropertyId())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(deleteItems)) { + deleteItems.stream().forEach(item -> { + item.setGmtModify(new Date()); + item.setMenderId(userId); + item.setDeleted(true); + }); + propertyItemRepository.batchUpdate(deleteItems, deleteItems.size()); + } + } + + // 2-add:新增property数据并新增对应的propertyItem数据 + for (Property property : addProperties) { + // 新增Property + property.setMenderId(userId); + property.setCreatorId(userId); + property.setModuleId(moduleId); + if (PropertyConstant.RESERVED_MODULE_CODES.contains(property.getCode().toLowerCase())) { + throw new Exception(property.getName() + "属性指定的code[" + property.getCode() + "]为系统内置code,请修改后重试"); + } + try { + propertyRepository.save(property); + } catch (Exception e) { + throw new Exception("创建属性失败"); + } + // 新增PropertyItem + if (CollectionUtils.isNotEmpty(property.getItemList())) { + property.getItemList().stream().forEach(item -> { + if (CollectionUtils.isNotEmpty(item.getItemList())) { + // 表格属性中结构项数据的下拉选项数据 转成 JSON 存储 + item.setItemValue(JSON.toJSONString(item.getItemList())); + } + item.setModuleId(property.getModuleId()); + item.setPropertyId(property.getId()); + item.setCreatorId(userId); + item.setMenderId(userId); + }); + propertyItemRepository.batchSave(property.getItemList(), property.getItemList().size()); + } + } + // 3-update:更新数据 + for (Property property : updateProperties) { + if(null != property.getPropertyPoolId()){ + property.setGmtModify(new Date()); + property.setMenderId(userId); + propertyRepository.update(property); + continue; + } + // 获取新增item数据 + List addItems = new ArrayList<>(); + if (!Common.ONE.equals(property.getTableType())){ + addItems = property.getItemList().stream().filter(item -> null == item.getId()).collect(Collectors.toList()); + addItems.stream().forEach(item -> { + item.setModuleId(property.getModuleId()); + item.setPropertyId(property.getId()); + item.setCreatorId(userId); + item.setMenderId(userId); + if (CollectionUtils.isNotEmpty(item.getItemList())) { + // 表格属性中结构项数据的下拉选项数据 转成 JSON 存储 + item.setItemValue(JSON.toJSONString(item.getItemList())); + } + }); + } + // 获取更新的item数据 + List updateItems = new ArrayList<>(); + List updateItemIds = new ArrayList<>(); + if (!Common.ONE.equals(property.getTableType())){ + updateItems = property.getItemList().stream().filter(item -> null != item.getId()).collect(Collectors.toList()); + updateItems.stream().forEach(item -> { + item.setMenderId(userId); + if (CollectionUtils.isNotEmpty(item.getItemList())) { + // 表格属性中结构项数据的下拉选项数据 转成 JSON 存储 + item.setItemValue(JSON.toJSONString(item.getItemList())); + } updateItemIds.add(item.getId()); + }); + } + // 根据当前属性id查询出之前的item + List updateOldItems = oldItems.stream() + .filter(item -> item.getPropertyId().equals(property.getId())).collect(Collectors.toList()); + // 获取需要删除的item数据(就是原始的减去现在的) + List deleteItems = updateOldItems.stream() + .filter(item -> !updateItemIds.contains(item.getId())).collect(Collectors.toList()); + deleteItems.stream().forEach(item -> { + item.setGmtModify(new Date()); + item.setMenderId(userId); + item.setDeleted(true); + }); + // 删除 更新的property数据中被删除的item数据 + if (CollectionUtils.isNotEmpty(deleteItems)) { + propertyItemRepository.batchUpdate(deleteItems, deleteItems.size()); + } + // 新增 更新的property数据中新增的item数据 + if (CollectionUtils.isNotEmpty(addItems)) { + propertyItemRepository.batchSave(addItems, addItems.size()); + } + // 更新 更新的property数据中更新的item数据 + if (CollectionUtils.isNotEmpty(updateItems)) { + propertyItemRepository.batchUpdate(updateItems, updateItems.size()); + } + property.setGmtModify(new Date()); + property.setMenderId(userId); + propertyRepository.update(property); + } + + // 4-对group的新增、更新、删除操作 + // 获取需要新增的group数据 + if (CollectionUtils.isNotEmpty(groups)) { + List addGroups = + groups.stream().filter(item -> null == item.getId()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(addGroups)) { + propertyGroupRepository.batchSave(addGroups, addGroups.size()); + } + // 获取需要更新的group数据 + List updateGroups = + groups.stream().filter(item -> null != item.getId()).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(updateGroups)) { + updateGroups.stream().forEach(item -> { + item.setMenderId(userId); + }); + propertyGroupRepository.batchUpdate(updateGroups, updateGroups.size()); + } + List groupIds = updateGroups.stream().map(PropertyGroup::getId).collect(Collectors.toList()); + // 获取需要删除的数据 + List deleteGroups = + oldGroups.stream().filter(item -> !groupIds.contains(item.getId())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(deleteGroups)) { + deleteGroups.stream().forEach(item -> { + item.setModuleId(userId); + item.setDeleted(true); + }); + propertyGroupRepository.batchUpdate(deleteGroups, deleteGroups.size()); + } + } + return new GeneralResult<>(true, "保存成功"); + } + + /** + * 数据校验 + * + * @param + * @throws Exception + */ + private void validate(List properties, List groups) throws Exception { + if (ListTool.isEmpty(properties)) { + throw new Exception("不可删除所有属性"); + } + // 校验属性以及属性的item数据 + Map codeMap = new HashMap<>(); + Map nameMap = new HashMap<>(); + for (Property property : properties) { + String code = property.getCode().toLowerCase(); + if (code == null || "".equals(code)) { + throw new Exception("属性编码不能为空"); + } + code = code.trim(); + Pattern compile = Pattern.compile( + "^(create|alter|select|update|union|and|or|delete|insert|trancate|char|substr|commit|ascii|declare|exec|count|show|into|drop|execute)$"); + if (compile.matcher(code).find()) { + throw new Exception("属性编码不能是关键字:" + code); + } + if (!code.matches("^[a-zA-Z][0-9a-zA-Z_]{0,}$")) { + throw new Exception("唯一标识必须以字母开头且由字母数字或者下划线组成"); + } + if (codeMap.get(code) != null) { + throw new Exception("属性编码重复:" + code); + } + codeMap.put(code, code); + String name = property.getName(); + if (name == null || "".equals(name)) { + throw new Exception("属性名称不能为空"); + } + if (nameMap.get(name) != null) { + throw new Exception("属性名称重复:" + name); + } + nameMap.put(name, name); + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + if (property.getType().equals(PropertyConstant.PropertyType.MULTILINETABLE) + || property.getType().equals(PropertyConstant.PropertyType.SINGLELINETABLE)) { + Map itemNameMap = new HashMap<>(); + Map itemCodeMap = new HashMap<>(); + List tableItems = property.getItemList(); + int i = 1; + for (PropertyItem tableItem : tableItems) { + String itemName = tableItem.getName(); + if (itemName == null || "".equals(itemName)) { + throw new Exception("结构项名称不能为空!"); + } + if (itemNameMap.get(itemName) != null) { + throw new Exception("结构项名称重复:" + itemName); + } + itemNameMap.put(itemName, itemName); + String itemCode = tableItem.getCode(); + if (org.apache.commons.lang3.StringUtils.isEmpty(itemCode)) { + throw new Exception("结构项ID不能为空"); + } + if (itemCodeMap.get(itemCode) != null) { + throw new Exception("结构项ID重复:" + itemCode); + } + itemCodeMap.put(itemCode, itemCode); + if (tableItem.getType().equals(PropertyConstant.PropertyType.SINGLESELECT) + || tableItem.getType().equals(PropertyConstant.PropertyType.MULTISELECT) + || tableItem.getType().equals(PropertyConstant.PropertyType.RADIO) + || tableItem.getType().equals(PropertyConstant.PropertyType.CHECKBOX)) { + validateItemValues(tableItem); + } + } + } else { + Map itemValueMap = new HashMap<>(); + Map itemNameMap = new HashMap<>(); + for (PropertyItem item : items) { + // value校验 + String itemValue = item.getValue(); + if (StringUtils.isEmpty(itemValue)) { + throw new Exception("枚举值不能为空"); + } + if (itemValueMap.get(itemValue) != null) { + throw new Exception("枚举值必须唯一"); + } + itemValueMap.put(itemValue, itemValue); + // name校验 + String itemName = item.getName(); + if (StringUtils.isEmpty(itemName)) { + throw new Exception("枚举值描述不能为空"); + } + if (itemNameMap.get(itemName) != null) { + throw new Exception("枚举值描述必须唯一"); + } + itemNameMap.put(itemName, itemName); + } + } + } + } + // 校验属性分组数据 + Map groupNameMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(groups)) { + for (PropertyGroup group : groups) { + String name = group.getName(); + if (name == null || "".equals(name)) { + throw new Exception("属性名称不能为空"); + } + if (groupNameMap.get(name) != null) { + throw new Exception("属性名称重复:" + name); + } + groupNameMap.put(name, name); + } + } + } + + private void validateItemValues(PropertyItem tableItem) throws Exception { + List itemValues = tableItem.getItemList(); + Map itemValueMap = new HashMap<>(); + Map itemNameMap = new HashMap<>(); + for (PropertyItem item : itemValues) { + String itemName = item.getName(); + if (org.apache.commons.lang3.StringUtils.isEmpty(itemName)) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值描述不能为空"); + } + if (itemNameMap.get(itemName) != null) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值描述必须唯一"); + } + itemNameMap.put(itemName, itemName); + String itemValue = item.getValue(); + if (org.apache.commons.lang3.StringUtils.isEmpty(itemValue)) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值不能为空"); + } + if (itemValueMap.get(itemValue) != null) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值必须唯一"); + } + itemValueMap.put(itemValue, itemValue); + } + } + + private void copyProperties(Property property, PropertyPool pool) + throws IllegalAccessException, InvocationTargetException { + Long id = property.getId(); + BeanUtilsBean.getInstance().copyProperties(property, pool); + property.setId(id); + } + + public void getGroups(List groupIds, Long groupId, Map> moduleGroups) { + List groups = moduleGroups.get(groupId); + if (CollectionUtils.isNotEmpty(groups)) { + for (ModuleGroup moduleGroup : groups) { + this.getGroups(groupIds, moduleGroup.getId(), moduleGroups); + } + } + groupIds.add(groupId); + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyPoolServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyPoolServiceImpl.java new file mode 100644 index 0000000..6ca9a20 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyPoolServiceImpl.java @@ -0,0 +1,424 @@ +package com.bocloud.ams.service.module.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyItem; +import com.bocloud.ams.entity.module.PropertyPool; +import com.bocloud.ams.entity.module.PropertyPoolItem; +import com.bocloud.ams.repository.module.PropertyItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.service.module.PropertyPoolService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Description: 属性池实现类 + * @Title: PropertyPoolServiceImpl + * @Author: majiali + * @CreateTime: 2022/5/5 14:14 + */ +@Slf4j +@Service("propertyPoolService") +public class PropertyPoolServiceImpl implements PropertyPoolService { + + @Autowired + private PropertyPoolRepository propertyPoolRepository; + @Autowired + private PropertyPoolItemRepository propertyPoolItemRepository; + @Autowired + private LockFactory lockFactory; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private PropertyItemRepository propertyItemRepository; + + @Override + public GeneralResult create(PropertyPool pool, Long userId) { + try { + if (judgeCodeExist(pool.getCode())) { + return new GeneralResult(false, "属性编码已经存在"); + } + if (PropertyConstant.RESERVED_MODULE_CODES.contains(pool.getCode().toLowerCase())) { + throw new Exception("属性编码[" + pool.getCode() + "]为系统内置编码,请修改后重试"); + } + validate(pool); + pool.setDeleted(false); + pool.setCreatorId(userId); + pool.setMenderId(userId); + pool.setGmtModify(new Date()); + pool.setGmtCreate(new Date()); + propertyPoolRepository.save(pool); + // 非引用类型的属性item才有值 + if (null == pool.getLinkModuleId()) { + List items = pool.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + for (PropertyPoolItem item : items) { + item.setDeleted(false); + item.setCreatorId(userId); + item.setMenderId(userId); + item.setGmtModify(new Date()); + item.setGmtCreate(new Date()); + item.setPropertyPoolId(pool.getId()); + List itemValueList = item.getItemList(); + if (CollectionUtils.isNotEmpty(itemValueList)) { + item.setItemValue(JSONObject.toJSONString(itemValueList)); + } + } + propertyPoolItemRepository.batchSave(items, 100); + } + } + return new GeneralResult<>(true, "属性新增成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool create fail:", e); + return new GeneralResult<>(false, "属性新增失败," + e.getMessage()); + } + } + + private boolean judgeCodeExist(String code) throws Exception { + PropertyPool temp = propertyPoolRepository.queryByCode(code); + return null != temp; + } + + /** + * 数据校验 + * + * @param pool + * @throws Exception + */ + private void validate(PropertyPool pool) throws Exception { + String code = pool.getCode().toLowerCase().trim(); + Pattern compile = Pattern.compile( + "^(create|alter|select|update|union|and|or|delete|insert|trancate|char|substr|commit|ascii|declare|exec|count|show|into|drop|execute)$"); + if (compile.matcher(code).find()) { + throw new Exception("属性编码不能是关键字:" + code); + } + if (!code.matches("^[a-zA-Z][0-9a-zA-Z_]{0,}$")) { + throw new Exception("唯一标识必须以字母开头且由字母数字或者下划线组成"); + } + List items = pool.getItemList(); + if (CollectionUtils.isEmpty(items)) { + return; + } + if (pool.getType().equals(PropertyConstant.PropertyType.MULTILINETABLE) + || pool.getType().equals(PropertyConstant.PropertyType.SINGLELINETABLE)) { + Map itemNameMap = new HashMap<>(); + Map itemValueMap = new HashMap<>(); + for (PropertyPoolItem tableItem : items) { + String itemName = tableItem.getName(); + if (StringUtils.isEmpty(itemName)) { + throw new Exception("结构项名称不能为空!"); + } + if (itemNameMap.get(itemName) != null) { + throw new Exception("结构项名称重复:" + itemName); + } + itemNameMap.put(itemName, itemName); + String itemValue = tableItem.getCode(); + if (StringUtils.isEmpty(itemValue)) { + throw new Exception("结构项ID不能为空"); + } + if (itemValueMap.get(itemValue) != null) { + throw new Exception("结构项ID重复:" + itemValue); + } + itemValueMap.put(itemValue, itemValue); + + if (tableItem.getType().equals(PropertyConstant.PropertyType.SINGLESELECT) + || tableItem.getType().equals(PropertyConstant.PropertyType.MULTISELECT) + || tableItem.getType().equals(PropertyConstant.PropertyType.RADIO) + || tableItem.getType().equals(PropertyConstant.PropertyType.CHECKBOX)) { + validateItemValues(tableItem); + } + } + } else { + + Map itemNameMap = new HashMap<>(); + Map itemValueMap = new HashMap<>(); + for (PropertyPoolItem item : items) { + String itemName = item.getName(); + if (StringUtils.isEmpty(itemName)) { + throw new Exception("枚举值描述不能为空!"); + } + if (itemNameMap.get(itemName) != null) { + // throw new Exception("属性选项名称重复:" + itemName); + throw new Exception("枚举值描述必须唯一"); + } + itemNameMap.put(itemName, itemName); + String itemValue = item.getValue(); + if (StringUtils.isEmpty(itemValue)) { + throw new Exception("枚举值不能为空"); + } + if (itemValueMap.get(itemValue) != null) { + // throw new Exception("属性选项值重复:" + itemValue); + throw new Exception("枚举值必须唯一"); + } + itemValueMap.put(itemValue, itemValue); + } + } + } + + private void validateItemValues(PropertyPoolItem tableItem) throws Exception { + List itemValues = tableItem.getItemList(); + Map itemValueMap = new HashMap<>(); + Map itemNameMap = new HashMap<>(); + for (PropertyPoolItem item : itemValues) { + String itemName = item.getName(); + if (StringUtils.isEmpty(itemName)) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值描述不能为空"); + } + if (itemNameMap.get(itemName) != null) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值描述必须唯一"); + } + itemNameMap.put(itemName, itemName); + String itemValue = item.getValue(); + if (StringUtils.isEmpty(itemValue)) { + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值不能为空"); + } + if (itemValueMap.get(itemValue) != null) { + // throw new Exception("结构项【" + tableItem.getName() + "】的属性选项值重复:" + itemValue); + throw new Exception("结构项【" + tableItem.getName() + "】的枚举值必须唯一"); + } + itemValueMap.put(itemValue, itemValue); + } + } + + @Override + public GeneralResult modify(PropertyPool pool, Long userId) { + String path = PropertyPoolServiceImpl.class.getSimpleName() + "_" + pool.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + PropertyPool temp = propertyPoolRepository.query(pool.getId()); + if (null == temp) { + return new GeneralResult<>(false, "属性不存在"); + } + validate(pool); + LocaleBeanUtils.copyProperties(temp, pool); + temp.setGmtModify(new Date()); + temp.setMenderId(userId); + propertyPoolRepository.update(temp); + // 非引用类型的属性item才有值 + if (null == pool.getLinkModuleId()) { + // 更新配置项 + updatePoolItem(pool, userId); + } + return new GeneralResult<>(true, "属性修改成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool modify fail:", e); + return new GeneralResult<>(false, "属性修改失败," + e.getMessage()); + } + } + + private void updatePoolItem(PropertyPool pool, Long userId) throws Exception { + List itemList = pool.getItemList(); + List oldItemList = propertyPoolItemRepository.listByPropertyPoolId(pool.getId()); + if (CollectionUtils.isEmpty(oldItemList)) { + if (CollectionUtils.isNotEmpty(itemList)) { + itemList.forEach(item -> { + item.setDeleted(false); + item.setCreatorId(userId); + item.setMenderId(userId); + item.setGmtModify(new Date()); + item.setGmtCreate(new Date()); + item.setPropertyPoolId(pool.getId()); + List itemValueList = item.getItemList(); + if (CollectionUtils.isNotEmpty(itemValueList)) { + item.setItemValue(JSONObject.toJSONString(itemValueList)); + } + }); + propertyPoolItemRepository.batchSave(itemList, 100); + } + } else { + if (CollectionUtils.isNotEmpty(itemList)) { + List addList = new ArrayList<>(); + List updateList = new ArrayList<>(); + Map> itemMap = + oldItemList.stream().collect(Collectors.groupingBy(PropertyPoolItem::getId)); + itemList.forEach(item -> { + if (null == item.getId() || 0L == item.getId()) { + item.setDeleted(false); + item.setCreatorId(userId); + item.setMenderId(userId); + item.setGmtModify(new Date()); + item.setGmtCreate(new Date()); + item.setPropertyPoolId(pool.getId()); + List itemValueList = item.getItemList(); + if (CollectionUtils.isNotEmpty(itemValueList)) { + item.setItemValue(JSONObject.toJSONString(itemValueList)); + } + addList.add(item); + } else { + itemMap.remove(item.getId()); + item.setMenderId(userId); + item.setGmtModify(new Date()); + item.setPropertyPoolId(pool.getId()); + List itemValueList = item.getItemList(); + if (CollectionUtils.isNotEmpty(itemValueList)) { + item.setItemValue(JSONObject.toJSONString(itemValueList)); + } + updateList.add(item); + } + }); + if (CollectionUtils.isNotEmpty(addList)) { + propertyPoolItemRepository.batchSave(addList, 100); + } + if (CollectionUtils.isNotEmpty(updateList)) { + propertyPoolItemRepository.batchUpdate(updateList, 100); + } + if (!itemMap.isEmpty()) { + propertyPoolItemRepository.deleteByIds(new ArrayList<>(itemMap.keySet()), userId); + } + } else { + propertyPoolItemRepository.deleteByPropertyPoolId(pool.getId(), userId); + } + } + } + + @Override + public GeneralResult remove(Long id, Long userId) { + String path = PropertyPoolServiceImpl.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + PropertyPool temp = propertyPoolRepository.query(id); + if (null == temp) { + return new GeneralResult<>(false, "属性不存在"); + } + final List propertyList = propertyRepository.queryListByPoolIds(id); + if (CollectionUtils.isNotEmpty(propertyList)) { + return new GeneralResult<>(false, "该属性已关联模型,请先解除关联"); + } + propertyPoolItemRepository.deleteByPropertyPoolId(id, userId); + propertyPoolRepository.delete(id, userId); + return new GeneralResult<>(true, "属性删除成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool remove fail:", e); + return new GeneralResult<>(false, "属性删除失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + PropertyPool pool = propertyPoolRepository.query(id); + if (null == pool) { + return new GeneralResult<>(false, "属性查询失败,数据不存在"); + } + dealPoolItem(pool); + return new GeneralResult<>(true, pool, "属性查询成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool detail query fail:", e); + return new GeneralResult<>(false, "属性查询失败"); + } + } + + @Override + public GeneralResult list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = propertyPoolRepository.count(pager.getParams()); + List list = this.propertyPoolRepository.list(pager); + if (CollectionUtils.isNotEmpty(list)) { + for (PropertyPool pool : list) { + dealPoolItem(pool); + } + } + GridBean bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("CmdbPropertyPool list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void dealPoolItem(PropertyPool pool) throws Exception { + if (PropertyConstant.TABLE_TYPE_ONE.equals(pool.getTableType())) { + List propertyIds = Arrays.asList(pool.getPropertyIds().split(",")).stream() + .map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); + // 查询不是引入属性池中的属性信息 + List poolItems = new ArrayList<>(); + List properties = propertyRepository.queryListNotLink(propertyIds); + if (CollectionUtils.isNotEmpty(properties)) { + // 查询属性项 + List items = + propertyItemRepository.queryByModuleIdAndPropertyIds(pool.getLinkModuleId(), propertyIds); + Map> itemsMap = + items.stream().collect(Collectors.groupingBy(PropertyItem::getPropertyId)); + PropertyPoolItem item; + for (Property property : properties) { + // 查询属性项 + item = new PropertyPoolItem(); + item.setName(property.getName()); + item.setType(property.getType()); + item.setCode(property.getCode()); + List propertyItems = itemsMap.get(property.getId()); + if (CollectionUtils.isNotEmpty(propertyItems)) { + item.setItemList( + JSONObject.parseArray(JSONObject.toJSONString(propertyItems), PropertyPoolItem.class)); + } + item.setPropertyId(property.getId()); + item.setModuleId(property.getModuleId()); + item.setPropertyPoolId(pool.getId()); + poolItems.add(item); + } + } + // 查询引入属性池中的属性信息 + List pools = propertyPoolRepository.listByPropertyIds(propertyIds); + if (CollectionUtils.isNotEmpty(pools)) { + List poolIds = pools.stream().map(PropertyPool::getId).collect(Collectors.toList()); + // 查询属性项 + List items = propertyPoolItemRepository.listByPropertyPoolIds(poolIds); + Map> itemsMap = + items.stream().collect(Collectors.groupingBy(PropertyPoolItem::getPropertyPoolId)); + for (PropertyPool property : pools) { + // 查询属性项 + PropertyPoolItem item = new PropertyPoolItem(); + item.setName(property.getName()); + item.setType(property.getType()); + item.setCode(property.getCode()); + item.setItemList(itemsMap.get(property.getId())); + item.setPropertyId(property.getId()); + item.setPropertyPoolId(pool.getId()); + poolItems.add(item); + } + } + pool.setItemList(poolItems); + } else { + List items = propertyPoolItemRepository.listByPropertyPoolId(pool.getId()); + if (CollectionUtils.isNotEmpty(items)) { + for (PropertyPoolItem item : items) { + if (StringUtils.isNotEmpty(item.getItemValue())) { + item.setItemList(JSONObject.parseArray(item.getItemValue(), PropertyPoolItem.class)); + } + } + } + pool.setItemList(items); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyServiceImpl.java new file mode 100644 index 0000000..efeaeb3 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/PropertyServiceImpl.java @@ -0,0 +1,155 @@ +package com.bocloud.ams.service.module.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.BeanUtilsBean; +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyItem; +import com.bocloud.ams.entity.module.PropertyPool; +import com.bocloud.ams.entity.module.PropertyPoolItem; +import com.bocloud.ams.repository.module.PropertyGroupRepository; +import com.bocloud.ams.repository.module.PropertyItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.module.RegularExpressionRepository; +import com.bocloud.ams.service.module.PropertyService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.Common; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Author 胡立伟 + * @Date 2022/5/9 0009 18:29 + * @Description: + */ +@Slf4j +@Service("propertyService") +public class PropertyServiceImpl implements PropertyService { + + @Autowired + PropertyRepository propertyRepository; + @Autowired + PropertyItemRepository propertyItemRepository; + @Autowired + PropertyGroupRepository propertyGroupRepository; + @Autowired + private PropertyPoolRepository propertyPoolRepository; + @Autowired + private PropertyPoolItemRepository propertyPoolItemRepository; + @Autowired + RegularExpressionRepository regularExpressionRepository; + + @Override + public GeneralResult detail(Long id) { + try { + Property property = propertyRepository.query(id); + if (null == property) { + return new GeneralResult<>(false, "没有此模型"); + } + List items = propertyItemRepository.queryByPropertyId(id); + this.propertyHandle(property, items); + return new GeneralResult<>(true, property, "查询成功"); + } catch (Exception e) { + log.error("propertyService detail fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public void propertyHandle(Property property, List items) throws Exception { + // 判断当前属性是否是引用池中的属性 + if (null != property.getPropertyPoolId()) { + PropertyPool pool = propertyPoolRepository.query(property.getPropertyPoolId()); + this.copyProperties(property, pool); + List poolItems = propertyPoolItemRepository.listByPropertyPoolId(pool.getId()); + List propertyItems = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(poolItems)) { + for (PropertyPoolItem poolItem : poolItems) { + PropertyItem propertyItem = new PropertyItem(); + LocaleBeanUtils.copyProperties(propertyItem, poolItem); + // 需要把当前属性的id赋值给copy过后的属性propertyItem + propertyItem.setPropertyId(property.getId()); + if (CollectionUtils.isNotEmpty(poolItem.getItemList())) { + propertyItem.setItemList(JSONObject.parseArray(poolItem.getItemValue(), PropertyItem.class)); + } + propertyItems.add(propertyItem); + } + } + // 把从池表中引用的属性 转化成 自定义的属性处理 + this.handleProperty(property, propertyItems); + } else { + this.handleProperty(property, items); + } + if (property.getRegexpId() != null) { + property.setRegularExpression(regularExpressionRepository.query(property.getRegexpId())); + } + } + + private void handleProperty(Property property, List items) { + // 如果是表格需要单独处理 + if (PropertyConstant.PropertyType.SINGLELINETABLE.equals(property.getType()) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(property.getType())) { + // 在是表格的前提下 如果是 引用已有模型的属性 还需要单独处理 + if (Common.ONE.equals(property.getTableType()) && null != property.getLinkModuleId() + && StringUtils.isNotEmpty(property.getPropertyIds())) { + List propertyIds = Arrays.asList(property.getPropertyIds().split(",")).stream() + .map(s -> Long.parseLong(s)).collect(Collectors.toList()); + List appointProperties = propertyRepository.appointPropertylist(propertyIds); + List appointItems = new ArrayList<>(); + for (Property appointProperty : appointProperties) { + PropertyItem appointItem = new PropertyItem(); + // todo + appointItem.setId(appointProperty.getId()); + appointItem.setPropertyId(appointProperty.getId()); + appointItem.setModuleId(appointProperty.getModuleId()); + appointItem.setName(appointProperty.getName()); + appointItem.setCode(appointProperty.getCode()); + appointItem.setType(appointProperty.getType()); + List propertyItems = + propertyItemRepository.queryByPropertyId(appointProperty.getId()); + if (CollectionUtils.isNotEmpty(propertyItems)) { + appointItem.setItemList(propertyItems); + } + appointItems.add(appointItem); + } + property.setItemList(appointItems); + } else { + List propertyItems = items.stream() + .filter(item -> item.getPropertyId().equals(property.getId())).collect(Collectors.toList()); + for (PropertyItem propertyItem : propertyItems) { + if (null != propertyItem.getItemValue()) { + propertyItem.setItemList(JSON.parseArray(propertyItem.getItemValue(), PropertyItem.class)); + } + } + property.setItemList(propertyItems); + } + } else { + List propertyItems = items.stream() + .filter(item -> item.getPropertyId().equals(property.getId())).collect(Collectors.toList()); + property.setItemList(propertyItems); + } + } + + private void copyProperties(Property property, PropertyPool pool) + throws IllegalAccessException, InvocationTargetException { + Long id = property.getId(); + BeanUtilsBean.getInstance().copyProperties(property, pool); + property.setId(id); + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RegularExpressionServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RegularExpressionServiceImpl.java new file mode 100644 index 0000000..2166ff0 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RegularExpressionServiceImpl.java @@ -0,0 +1,48 @@ +package com.bocloud.ams.service.module.impl; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.bocloud.ams.entity.module.RegularExpression; +import com.bocloud.ams.repository.module.RegularExpressionRepository; +import com.bocloud.ams.service.module.RegularExpressionService; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.megatron.common.model.GeneralResult; + +import lombok.extern.slf4j.Slf4j; + +/** + * CiRegularExpression Service实现层 + * + * @author 胡立伟 + * @Version 1.0 + * @since 2017年9月15日 + */ +@Slf4j +@Service("regularExpressionService") +public class RegularExpressionServiceImpl implements RegularExpressionService { + + @Autowired + private RegularExpressionRepository regularExpressionRepository; + + @Override + public GeneralResult> list(final String type) { + try { + List expressions = regularExpressionRepository.listAll(); + // 模型属性的类别为数据加密的单独处理 + if (type.equals(PropertyConstant.PropertyType.TEXTENCRYPT)) { + expressions = expressions.stream().filter(item -> null != item.getCode()) + .filter(item -> item.getCode().equals("SIMPLEPASSWORD") || item.getCode().equals("COMPLEXPASSWORD")) + .collect(Collectors.toList()); + } + return new GeneralResult<>(true, expressions, "查询成功"); + } catch (Exception e) { + log.error("Query cmdbRegularExpression list error:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationCategoryServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationCategoryServiceImpl.java new file mode 100644 index 0000000..a3df794 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationCategoryServiceImpl.java @@ -0,0 +1,245 @@ +package com.bocloud.ams.service.module.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.Relation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.entity.module.TopologyConfig; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.RelationCategoryRepository; +import com.bocloud.ams.repository.module.RelationRepository; +import com.bocloud.ams.repository.module.TopologyConfigRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.instance.InstanceRelationService; +import com.bocloud.ams.service.module.RelationCategoryService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Description: 关联类型分组管理 + * @Title: RelationCategoryServiceImpl + * @Author: majiali + * @CreateTime: 2022/5/7 16:59 + */ +@Slf4j +@Service("relationCategoryService") +public class RelationCategoryServiceImpl implements RelationCategoryService { + + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private RelationRepository relationRepository; + @Autowired + private LockFactory lockFactory; + @Autowired + private InstanceRelationService instanceRelationService; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private TopologyConfigRepository topologyConfigRepository; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + + @Override + public GeneralResult create(RelationCategory relationCategory, Long userId) { + try { + + if (judgeNameExist(relationCategory.getName())) { + return new GeneralResult<>(false, "关联类型分组名称已经存在"); + } + if (judgeCodeExist(relationCategory.getCode())) { + return new GeneralResult<>(false, "关联类型分组编码已经存在"); + } + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(); + if (instanceRelationRepository.countTable(relationTable) > 0) { + log.error("创建CI实例关系表{}失败", relationTable); + return new GeneralResult<>(false, "创建失败," + relationTable + "实例关系表已存"); + } + relationCategory.setDeleted(false); + relationCategory.setCreatorId(userId); + relationCategory.setMenderId(userId); + relationCategory.setGmtModify(new Date()); + relationCategory.setGmtCreate(new Date()); + relationCategoryRepository.save(relationCategory); + // 生成CI实例关系表 + GeneralResult result = + instanceRelationService.createTable(relationCategory.getCode().toLowerCase(), userId); + if (result.isFailed()) { + return result; + } + return new GeneralResult<>(true, "关联类型分组新增成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory create fail:", e); + return new GeneralResult<>(false, "关联类型分组新增失败"); + } + } + + private boolean judgeCodeExist(String code) throws Exception { + boolean flag = false; + RelationCategory temp = relationCategoryRepository.queryByCode(code); + if (null != temp) { + flag = true; + } + return flag; + } + + private boolean judgeNameExist(String name) throws Exception { + boolean flag = false; + RelationCategory temp = relationCategoryRepository.queryByName(name); + if (null != temp) { + flag = true; + } + return flag; + } + + @Override + public GeneralResult modify(RelationCategory relationCategory, Long userId) { + String path = RelationCategoryServiceImpl.class.getSimpleName() + "_" + relationCategory.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + RelationCategory temp = relationCategoryRepository.query(relationCategory.getId()); + if (null == temp) { + return new GeneralResult<>(false, "关联类型分组不存在"); + } + RelationCategory tempByName = relationCategoryRepository.queryByName(relationCategory.getName()); + if(null != tempByName && !tempByName.getId().equals(relationCategory.getId())){ + return new GeneralResult<>(false, "关联类型分组名称已经存在"); + } + LocaleBeanUtils.copyProperties(temp, relationCategory); + temp.setGmtModify(new Date()); + temp.setMenderId(userId); + relationCategoryRepository.update(temp); + return new GeneralResult<>(true, "关联类型分组修改成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory modify fail:", e); + return new GeneralResult<>(false, "关联类型分组修改失败"); + } + } + + @Override + public GeneralResult remove(Long id, Long userId) { + String path = RelationCategoryServiceImpl.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + RelationCategory temp = relationCategoryRepository.query(id); + if (null == temp) { + return new GeneralResult<>(false, "关联类型分组不存在"); + } + List relationList = relationRepository.queryByCategoryId(id); + if (CollectionUtils.isNotEmpty(relationList)) { + return new GeneralResult<>(false, "该分组下有内容,不可删除"); + } + final List topologyConfigs = topologyConfigRepository.queryListBycategoryId(id); + if (CollectionUtils.isNotEmpty(topologyConfigs)) { + return new GeneralResult<>(false, "该分组已被实例拓扑使用,不可删除!"); + } + relationCategoryRepository.delete(id, userId); + // 删除CI资源关系表 + GeneralResult result = instanceRelationService.dropTable(temp.getCode().toLowerCase(), userId); + if (result.isFailed()) { + return result; + } + return new GeneralResult<>(true, "关联类型分组删除成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory remove fail:", e); + return new GeneralResult<>(false, "关联类型分组删除失败"); + } + } + + @Override + public GeneralResult list(Pager pager) { + try { + GridBean gridBean; + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + Boolean simple = pager.getSimple(); + if (null == simple) { + simple = false; + } + int total = relationCategoryRepository.count(pager.getParams()); + if (simple) { + List beans = relationCategoryRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.relationCategoryRepository.list(pager); + gridBean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult listAll(List params, Map sorter) { + try { + params = Optional.ofNullable(params).orElse(new ArrayList<>()); + sorter = Optional.ofNullable(sorter).orElse(new HashMap<>()); + sorter.put(Common.ID, Common.ONE); + List beans = relationCategoryRepository.list(params, sorter); + return new GeneralResult<>(true, beans, "查询成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult> moduleRelationList(Long id, Long moduleId) { + try { + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + return GeneralResult.FAILED("模型数据不存在"); + } + RelationCategory category = relationCategoryRepository.query(id); + if (null == category) { + return GeneralResult.FAILED("关联类型分组数据不存在"); + } + // 查询模型关系 + List relations = moduleRelationRepository.query(id, moduleId); + return new GeneralResult<>(true, relations, "查询模型关系成功!"); + } catch (Exception e) { + log.error("CmdbModuleRelation moduleRelationList query fail:", e); + return new GeneralResult<>(false, "查询模型关系失败"); + } + } + + @Override + public GeneralResult listByModuleId(Long moduleId) { + try { + List list = relationCategoryRepository.listByModuleId(moduleId); + return new GeneralResult<>(true, list, "查询成功"); + } catch (Exception e) { + log.error("CmdbRelationCategory list query by moduleId fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationServiceImpl.java new file mode 100644 index 0000000..1cc9f60 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/RelationServiceImpl.java @@ -0,0 +1,145 @@ +package com.bocloud.ams.service.module.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.beanutils.locale.LocaleBeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.Relation; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.module.RelationCategoryRepository; +import com.bocloud.ams.repository.module.RelationRepository; +import com.bocloud.ams.service.module.RelationService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.SimpleBean; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @Description: 关联类型管理 + * @Title: RelationServiceImpl + * @Author: majiali + * @CreateTime: 2022/5/7 16:59 + */ +@Slf4j +@Service("relationService") +public class RelationServiceImpl implements RelationService { + + @Autowired + private RelationRepository relationRepository; + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private LockFactory lockFactory; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + + @Override + public GeneralResult create(Relation relation, Long userId) { + try { + RelationCategory category = relationCategoryRepository.query(relation.getCategoryId()); + if (null == category) { + return new GeneralResult<>(false, "关联类型分组不存在"); + } + if (judgeCodeExist(relation.getCode(), relation.getCategoryId())) { + return new GeneralResult<>(false, "关联类型编码已经存在"); + } + relation.setDeleted(false); + relation.setCreatorId(userId); + relation.setMenderId(userId); + relation.setGmtModify(new Date()); + relation.setGmtCreate(new Date()); + relationRepository.save(relation); + return new GeneralResult<>(true, "关联类型新增成功"); + } catch (Exception e) { + log.error("CmdbRelation create fail:", e); + return new GeneralResult<>(false, "关联类型新增失败"); + } + } + + private boolean judgeCodeExist(String code, Long categoryId) throws Exception { + Relation temp = relationRepository.queryByCode(code, categoryId); + return null != temp; + } + + @Override + public GeneralResult modify(Relation relation, Long userId) { + String path = RelationServiceImpl.class.getSimpleName() + "_" + relation.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + Relation temp = relationRepository.query(relation.getId()); + if (null == temp) { + return new GeneralResult<>(false, "关联类型不存在"); + } + LocaleBeanUtils.copyProperties(temp, relation); + temp.setGmtModify(new Date()); + temp.setMenderId(userId); + relationRepository.update(temp); + return new GeneralResult<>(true, "关联类型修改成功"); + } catch (Exception e) { + log.error("CmdbRelation modify fail:", e); + return new GeneralResult<>(false, "关联类型修改失败"); + } + } + + @Override + public GeneralResult remove(Long id, Long userId) { + String path = RelationServiceImpl.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + Relation temp = relationRepository.query(id); + if (null == temp) { + return new GeneralResult<>(false, "关联类型不存在"); + } + // 查询模型关系是否有使用该关系 + List relations = moduleRelationRepository.queryByRelationId(id); + if (!CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(false, "该关系在模型关系中被使用,不可删除"); + } + relationRepository.delete(id, userId); + return new GeneralResult<>(true, "关联类型删除成功"); + } catch (Exception e) { + log.error("CmdbRelation remove fail:", e); + return new GeneralResult<>(false, "关联类型删除失败"); + } + } + + @Override + public GeneralResult list(Pager pager) { + try { + GridBean gridBean; + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + Boolean simple = null == pager.getSimple() ? false : pager.getSimple(); + int total = relationRepository.count(pager.getParams()); + if (simple) { + List beans = relationRepository.list(pager.getParams(), pager.getSorter()); + gridBean = new GridBean<>(1, 1, total, beans); + } else { + List list = this.relationRepository.list(pager); + gridBean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + } + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("Relation list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/TopologyConfigServiceImpl.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/TopologyConfigServiceImpl.java new file mode 100644 index 0000000..3cbfbae --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/module/impl/TopologyConfigServiceImpl.java @@ -0,0 +1,1427 @@ +package com.bocloud.ams.service.module.impl; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.ColumnAndSearchItemModel; +import com.bocloud.ams.entity.model.ColumnModel; +import com.bocloud.ams.entity.model.InstanceModel; +import com.bocloud.ams.entity.model.InstanceNodeModel; +import com.bocloud.ams.entity.model.InstanceRelationModel; +import com.bocloud.ams.entity.model.InstanceTopo; +import com.bocloud.ams.entity.model.PathModel; +import com.bocloud.ams.entity.model.RequestInstanceTopologyModel; +import com.bocloud.ams.entity.model.ResponseInstanceTopologyModel; +import com.bocloud.ams.entity.model.SearchConfigModel; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyItem; +import com.bocloud.ams.entity.module.PropertyPoolItem; +import com.bocloud.ams.entity.module.RelationCategory; +import com.bocloud.ams.entity.module.TopologyConfig; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRelationRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.PropertyItemRepository; +import com.bocloud.ams.repository.module.PropertyPoolItemRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.module.RelationCategoryRepository; +import com.bocloud.ams.repository.module.TopologyConfigRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.module.TopologyConfigService; +import com.bocloud.ams.service.utils.GraphAlgorithmUtils; +import com.bocloud.ams.service.utils.PropertyConstant; +import com.bocloud.ams.service.utils.paginationUtil; +import com.google.common.collect.Lists; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.GridBean; +import com.megatron.common.model.Pager; +import com.megatron.common.model.Param; +import com.megatron.common.model.Sign; +import com.megatron.common.utils.Common; +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/12 17:41 + */ +@Slf4j +@Service("topologyConfigService") +public class TopologyConfigServiceImpl implements TopologyConfigService { + + @Autowired + private LockFactory lockFactory; + @Autowired + private TopologyConfigRepository topologyConfigRepository; + @Autowired + private ModuleRelationRepository moduleRelationRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private RelationCategoryRepository relationCategoryRepository; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private PropertyItemRepository propertyItemRepository; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private PropertyPoolItemRepository propertyPoolItemRepository; + @Autowired + private InstanceRepository instanceRepository; + + @Override + public GeneralResult> list(Pager pager) { + try { + pager.setParams(Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>())); + pager.setSorter(Optional.ofNullable(pager.getSorter()).orElse(new HashMap<>())); + pager.getSorter().put(Common.ID, Common.ONE); + int total = topologyConfigRepository.count(pager.getParams()); + List list = this.topologyConfigRepository.list(pager); + for (TopologyConfig config : list) { + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null != relationCategory) { + config.setCategoryName(relationCategory.getName()); + } + CiModule startModule = moduleRepository.query(config.getStartModuleId()); + if (null != startModule) { + config.setStartModuleName(startModule.getName()); + } + if (StringUtils.isNotEmpty(config.getWayModuleIds())) { + config.setWayModuleId(Arrays.stream(config.getWayModuleIds().split(",")).map(Long::valueOf).collect(Collectors.toList())); + } + if (StringUtils.isNotEmpty(config.getIgnoreModuleIds())) { + config.setIgnoreModuleId(Arrays.stream(config.getIgnoreModuleIds().split(",")).map(Long::valueOf).collect(Collectors.toList())); + } + if (StringUtils.isNotEmpty(config.getTopologyPath())) { + List moduleIds = Arrays.stream(config.getTopologyPath().split(",")).map(Long::valueOf).collect(Collectors.toList()); + List modules = moduleRepository.queryModuleListByIds(moduleIds); + String topologyPathName = modules.stream().map(CiModule::getName).collect(Collectors.joining("-")); + config.setTopologyPathName(topologyPathName); + } + } + GridBean bean = new GridBean<>(pager.getPage(), pager.getRows(), total, list); + return new GeneralResult<>(true, bean, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService list query fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult save(TopologyConfig config, Long target) { + try { + if (StringUtils.isEmpty(config.getConfigType())) { + config.setConfigType("PATCH"); + } + int sameName = topologyConfigRepository.countSameNameOrCode(config.getName(), null, config.getConfigType()); + if (sameName > 0) { + return new GeneralResult<>(false, "添加失败,该拓扑名称名称已存在,请尝试其他名称"); + } + if (CollectionUtils.isNotEmpty(config.getIgnoreModuleId())) { + List ignores = config.getIgnoreModuleId().stream().map(item -> String.valueOf(item)).collect(Collectors.toList()); + config.setIgnoreModuleIds(ignores.stream().collect(Collectors.joining(","))); + } + if (CollectionUtils.isNotEmpty(config.getWayModuleId())) { + List ways = config.getWayModuleId().stream().map(item -> String.valueOf(item)).collect(Collectors.toList()); + config.setWayModuleIds(ways.stream().collect(Collectors.joining(","))); + } + config.setGmtCreate(new Date()); + config.setGmtModify(new Date()); + config.setCreatorId(target); + config.setMenderId(target); + topologyConfigRepository.save(config); + return new GeneralResult<>(true, "创建成功"); + } catch (Exception e) { + log.error("topologyConfigService save fail:", e); + return new GeneralResult<>(false, "创建失败"); + } + } + + @Override + public GeneralResult modify(TopologyConfig config, Long target) { + String path = TopologyConfig.class.getSimpleName() + "_" + config.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + int sameName = topologyConfigRepository.countSameNameOrCode(config.getName(), config.getId(), config.getConfigType()); + if (sameName > 0) { + return new GeneralResult<>(false, "修改失败,该拓扑名称名称已存在,请尝试其他名称"); + } + if (CollectionUtils.isNotEmpty(config.getIgnoreModuleId())) { + List ignores = config.getIgnoreModuleId().stream().map(item -> String.valueOf(item)).collect(Collectors.toList()); + config.setIgnoreModuleIds(ignores.stream().collect(Collectors.joining(","))); + } + if (CollectionUtils.isNotEmpty(config.getWayModuleId())) { + List ways = config.getWayModuleId().stream().map(item -> String.valueOf(item)).collect(Collectors.toList()); + config.setWayModuleIds(ways.stream().collect(Collectors.joining(","))); + } + config.setGmtModify(new Date()); + config.setMenderId(target); + topologyConfigRepository.update(config); + return new GeneralResult<>(true, "修改成功"); + } catch (Exception e) { + log.error("topologyConfigService modify fail:", e); + return new GeneralResult<>(false, "修改失败"); + } + } + + @Override + public GeneralResult remove(Long id, Long target) { + String path = TopologyConfig.class.getSimpleName() + "_" + id; + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "拓扑实例不存在"); + } + topologyConfigRepository.delete(id, target); + return new GeneralResult<>(true, "删除成功"); + } catch (Exception e) { + log.error("topologyConfigService remove fail:", e); + return new GeneralResult<>(false, "删除失败"); + } + } + + @Override + public GeneralResult detail(Long id) { + try { + TopologyConfig config = topologyConfigRepository.query(id); + if ("PATCH".equalsIgnoreCase(config.getConfigType())) { + String message = this.escapeData(config); + if (null != message) { + return new GeneralResult<>(false, message); + } + } else { + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null != relationCategory) { + config.setCategoryName(relationCategory.getName()); + } + CiModule startModule = moduleRepository.query(config.getStartModuleId()); + if (null != startModule) { + config.setStartModuleName(startModule.getName()); + } + } + return new GeneralResult<>(true, config, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService detail fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 根据起始模型查询最大拓扑层级 + *

+ * 本接口实现思路:在categoryId对应的拓扑图中,获取以startModuleId作为头结点或者是终点的所有路径中,长度最大的那条路径的长度。 + * 具体实现: + * startModuleId作为头结点的路径: 获取以startModuleId为sourceId的数据所以应的树,然后获取这棵树所有路径集合。 + * startModuleId作为终点的路径: 获取以startModuleId为targetId的数据所以应的树,然后获取这棵树所有路径集合。 + * 获取两个路径集合中长度最大的路径的长度,作为为此拓扑模型中以startModuleId为源的最大的拓扑层级。 + * + * @param categoryId + * @param startModuleId + * @return + */ + @Override + public GeneralResult maxLevel(Long categoryId, Long startModuleId) { + RequestInstanceTopologyModel topologyModel = new RequestInstanceTopologyModel(); + topologyModel.setCategoryId(categoryId); + topologyModel.setStartModuleId(startModuleId); + try { + //获取起始模型为源id,对应的路径集合。 + GeneralResult>>> checkData = this.checkData(topologyModel); + if (checkData.isFailed()) { + return new GeneralResult<>(false, checkData.getMessage()); + } + //校验数据 + List> lists = new ArrayList<>(); + Map>> data = checkData.getData(); + for (Boolean aBoolean : data.keySet()) { + if (null != data.get(aBoolean)) { + lists.addAll(data.get(aBoolean)); + } + } + //移除集合中每个元素中所有为null的数据 + if (CollectionUtils.isEmpty(lists)) { + return new GeneralResult<>(true, 1, "查询最大层级成功"); + } + Integer maxSize = lists.stream().mapToInt(item -> item.size()).max().getAsInt(); + return new GeneralResult<>(true, maxSize, "查询最大层级成功"); + } catch (Exception e) { + log.error("topologyConfigService maxLevel fail:", e); + return new GeneralResult<>(false, "查询最大层级失败"); + } + } + + /** + * 获取拓扑路径 + *

+ * 接口实现思路: + * + * @param categoryId 拓扑图id + * @param startModuleId 起始模型id + * @param topologyLevel 拓扑层级 + * @param ignoreModuleId 忽略的拓扑 + * @param wayModuleId + * @return + */ + @Override + public GeneralResult> topologyPath(Long categoryId, Long startModuleId, Integer topologyLevel, String ignoreModuleId, String wayModuleId) { + try { + RequestInstanceTopologyModel topologyModel = new RequestInstanceTopologyModel(); + topologyModel.setCategoryId(categoryId); + topologyModel.setStartModuleId(startModuleId); + topologyModel.setTopologyLevel(topologyLevel); + if (StringUtils.isNotEmpty(ignoreModuleId)) { + List ignoreModuleIds = Arrays.asList(ignoreModuleId.split(",")).stream().map(item -> Long.valueOf(item)).collect(Collectors.toList()); + topologyModel.setIgnoreModuleId(ignoreModuleIds); + } + if (StringUtils.isNotEmpty(wayModuleId)) { + List wayModuleIds = Arrays.asList(wayModuleId.split(",")).stream().map(item -> Long.valueOf(item)).collect(Collectors.toList()); + topologyModel.setWayModuleId(wayModuleIds); + } + List pathModels = new ArrayList<>(); + //获取起始模型为源id,对应的路径集合 + GeneralResult>>> mapGeneralResult = this.checkData(topologyModel); + if (mapGeneralResult.isFailed()) { + return new GeneralResult<>(false, mapGeneralResult.getMessage()); + } + // 转化成返回的数据 + List moduleList = moduleRepository.all(); + Map>> data = mapGeneralResult.getData(); + for (Boolean aBoolean : data.keySet()) { + if (CollectionUtils.isNotEmpty(data.get(aBoolean))) { + // 获取拓扑路径(根据 忽略模型、必经模型、路径层级 等条件) + this.getPathModelList(data.get(aBoolean), moduleList, topologyLevel, pathModels, aBoolean, topologyModel); + } + } + //去重 + List pathModelList = pathModels.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PathModel::getTopologyPath))), ArrayList::new)); + return new GeneralResult<>(true, pathModelList, "查询拓扑路径成功"); + } catch (Exception e) { + log.error("topologyConfigService topologyPath fail:", e); + return new GeneralResult<>(false, "查询拓扑路径失败"); + } + } + + /** + * 获取查询项以及列表项 + * 功能:1:获取搜索项以及搜索项下拉框的值。2:动态获取表格的列数据 + * + * @param id + * @return + */ + @Override + public GeneralResult searchItemList(Long id) { + try { + ColumnAndSearchItemModel itemModel = new ColumnAndSearchItemModel(); + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + // 获取拓扑路径模型id + // 将拓扑路径模型id类型转成Long类型 + List moduleIds = Arrays.asList(config.getTopologyPath().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + List searchConfigs = new ArrayList<>(); + // 根据模型id查询模型信息 + List modules = moduleRepository.queryModuleListByIds(moduleIds); + if (CollectionUtils.isEmpty(modules)) { + return new GeneralResult<>(false, "没有对应的模型数据"); + } + // 1:处理搜索条件(搜索框返回的顺序要和拓扑路径中模型的顺序一致) + for (Long moduleId : moduleIds) { + CiModule module = modules.stream().filter(item -> item.getId().equals(moduleId)).findFirst().orElse(null); + if (null == module) { + continue; + } + searchConfigs.add(new SearchConfigModel(moduleId, module.getName(), module.getCode(), "Select")); + } + itemModel.setSearchConfigs(searchConfigs); + // 2:处理搜索条件的下拉框的值 + GeneralResult>> resourceData = this.getResourceData(config, moduleIds); + if (resourceData.isFailed()) { + return new GeneralResult<>(false, resourceData.getMessage()); + } + //获取拓扑路径对应的资源数据 + List> levelRelationList = resourceData.getData(); + List columns = new ArrayList<>(); + // 获取 模型id 找到 各个模型的实例集合 + for (SearchConfigModel searchConfig : itemModel.getSearchConfigs()) { + ColumnModel columnModel = new ColumnModel(); + if (CollectionUtils.isNotEmpty(levelRelationList)) { + List> data = new ArrayList<>(); + //获取当前搜索项对应的资源数据并去重得到对应的下拉框数据 + levelRelationList.stream().flatMap(instanceModels -> instanceModels.stream()).filter(item -> item.getModuleId().equals(searchConfig.getModuleId())).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InstanceModel::getInstanceId))), ArrayList::new)).forEach(item -> { + Map map = new HashMap<>(); + map.put("id", item.getInstanceId()); + map.put("name", item.getInstanceName()); + data.add(map); + }); + searchConfig.setData(data); + } + columnModel.setLabel(searchConfig.getLabel()); + columnModel.setProp(searchConfig.getValue()); + columns.add(columnModel); + } + // 3:处理列表集合 + List properties = propertyRepository.listIsTitleByModuleId(moduleIds.get(moduleIds.size() - 1)); + List finalProperties = properties.stream().filter(item -> !item.getCode().equals("name")).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(finalProperties)) { + for (Property property : finalProperties) { + columns.add(new ColumnModel(property.getName(), property.getCode())); + } + } + itemModel.setColumns(columns); + return new GeneralResult<>(true, itemModel, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService searchItemList fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 查询资源列表 + * + * @param pager + * @return + */ + @Override + public GeneralResult>> resourcelist(Pager pager) { + try { + GridBean> gridBean = null; + // 编辑返回数据格式 + List> lists = new ArrayList<>(); + if (CollectionUtils.isEmpty(pager.getParams()) || MapUtils.isEmpty(pager.getParams().get(0).getParam()) || null == pager.getParams().get(0).getParam().get("id")) { + return new GeneralResult<>(false, "id 不能为空"); + } + String id = pager.getParams().get(0).getParam().get("id").toString(); + TopologyConfig config = topologyConfigRepository.query(Long.valueOf(id)); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + // 将拓扑路径模型id类型转成Long类型 + List moduleIds = Arrays.asList(config.getTopologyPath().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + GeneralResult>> resourceData = this.getResourceData(config, moduleIds); + if (resourceData.isFailed()) { + return new GeneralResult<>(false, resourceData.getMessage()); + } else if (resourceData.isSuccess()) { + if (CollectionUtils.isEmpty(resourceData.getData())) { + gridBean = new GridBean<>(pager.getPage(), pager.getRows(), 0, lists); + return new GeneralResult<>(true, gridBean, "查询成功"); + } + } + //获取拓扑路径对应的资源数据 + List> levelRelationList = resourceData.getData(); + // 通过pager传过来的搜索参数过滤数据 + List> relationModelList = this.pagerFilter(levelRelationList, pager); + if (CollectionUtils.isEmpty(relationModelList)) { + gridBean = new GridBean<>(pager.getPage(), pager.getRows(), 0, lists); + return new GeneralResult<>(true, gridBean, "查询成功"); + } + // 此时先做分页 + Map pagination = paginationUtil.pagination(relationModelList, pager.getPage(), pager.getRows()); + // 获取分页后的数据 + List> paginations = (List>) pagination.get("list"); + // 获取每行数据中最后那个实例的实例id的集合。 + List lastInstanceIds = new ArrayList<>(); + for (List links : paginations) { + InstanceModel relationModel = links.get(links.size() - 1); + lastInstanceIds.add(relationModel.getInstanceId()); + } + // 获取模型code 从而才能找到对应的实例表 + String lastModuleCode = paginations.get(0).get(paginations.get(0).size() - 1).getModuleCode(); + // 拓扑路径最后一个模型的实例表是 + String lastInstanceTable = CmdbUtils.CMDB_INSTANCE_VALUE + lastModuleCode.toLowerCase(); + // 根据lastInstanceIds以及模型属性为列表项的propertyIds 查询 lastInstanceTable表中的数据 + List properties = propertyRepository.listIsTitleByModuleId(moduleIds.get(moduleIds.size() - 1)); + //获取需要转义的属性数据 + List propertyList = properties.stream().filter(item -> item.getType().equals(PropertyConstant.PropertyType.SINGLESELECT) || item.getType().equals(PropertyConstant.PropertyType.MULTISELECT) || item.getType().equals(PropertyConstant.PropertyType.RADIO) || item.getType().equals(PropertyConstant.PropertyType.CHECKBOX)).collect(Collectors.toList()); + List propertyIds = properties.stream().filter(item -> !item.getCode().equals("name")).map(Property::getId).collect(Collectors.toList()); + + // 获取指定实例的指定属性的数据列表 + List instanceValues = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(propertyIds)) { + instanceValues = instanceValueRepository.queryByInstanceIdsAndPropertyIds(lastInstanceTable, lastInstanceIds, propertyIds); + } + // 对每行数据进行循环 + for (List links : paginations) { + Map map = new HashMap<>(); + for (InstanceModel link : links) { + // 对于模型name使用对应的模型code作为key值 + map.put(link.getModuleCode(), link.getInstanceName()); + map.put(link.getModuleCode() + "_instanceId", link.getInstanceId()); + map.put(link.getModuleCode() + "_moduleId", link.getModuleId()); + } + // 获取每行中剩余属性数据 + if (CollectionUtils.isNotEmpty(instanceValues)) { + List values = instanceValues.stream().filter(item -> item.getInstanceId().equals(links.get(links.size() - 1).getInstanceId())).collect(Collectors.toList()); + for (InstanceValue value : values) { + Property property = propertyList.stream().filter(item -> item.getId().equals(value.getPropertyId())).findFirst().orElse(null); + //if内是转义 + if (null != property) { + List listString = Arrays.asList(value.getPropertyValue().replace("[", "").replace("]", "").replace("\"", "").split(",")); + if (CollectionUtils.isEmpty(listString)) { + continue; + } + List list = new ArrayList<>(); + List propertyItems = new ArrayList<>(); + if (null != property.getPropertyPoolId()) { + List propertyPoolItems = propertyPoolItemRepository.listByPropertyPoolId(property.getPropertyPoolId()); + BeanUtils.copyProperties(propertyPoolItems, propertyItems); + } else { + propertyItems = propertyItemRepository.queryByPropertyId(property.getId()); + } + if (CollectionUtils.isNotEmpty(propertyItems)) { + for (String s : listString) { + PropertyItem propertyItem = propertyItems.stream().filter(item -> item.getValue().equals(s)).findFirst().orElse(null); + if (null != propertyItem) { + list.add(propertyItem.getName()); + } + } + } + map.put(value.getPropertyCode(), StringUtils.join(list, ',')); + } else { + map.put(value.getPropertyCode(), value.getPropertyValue()); + } + } + } + lists.add(map); + } + gridBean = new GridBean<>(pager.getPage(), pager.getRows(), (int) pagination.get("totalCount"), lists); + return new GeneralResult<>(true, gridBean, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService resourcelist fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 获取拓扑路径下的资源列表 + * + * @param config + * @param moduleIds + * @return + */ + private GeneralResult>> getResourceData(TopologyConfig config, List moduleIds) { + try { + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null == relationCategory) { + return new GeneralResult<>(false, "没有对应的拓扑分组"); + } + List mapList = new ArrayList<>(); + for (int i = 0; i < moduleIds.size() - 1; i++) { + InstanceRelationModel instanceRelationModel = new InstanceRelationModel(); + instanceRelationModel.setSourceModuleId(moduleIds.get(i)); + instanceRelationModel.setTargetModuleId(moduleIds.get(i + 1)); + mapList.add(instanceRelationModel); + } + // 得到要查询的表名 + String relationTable = "ci_instance_relation_" + relationCategory.getCode().toLowerCase(); + // 通过 in(通过拓扑路径中的模型id)这样才能过滤出当前拓扑路径上的所有有关系的数据 + List allRelations = new ArrayList<>(); + for (InstanceRelationModel instanceRelationModel : mapList) { + List instanceRelationsForward = instanceRelationRepository.queryByModuleIds(relationTable, instanceRelationModel.getSourceModuleId(), instanceRelationModel.getTargetModuleId()); + if (CollectionUtils.isNotEmpty(instanceRelationsForward)) { + allRelations.addAll(instanceRelationsForward); + } + List instanceRelationsReverse = instanceRelationRepository.queryByModuleIds(relationTable, instanceRelationModel.getTargetModuleId(), instanceRelationModel.getSourceModuleId()); + if (CollectionUtils.isNotEmpty(instanceRelationsReverse)) { + allRelations.addAll(instanceRelationsReverse); + } + } + if (CollectionUtils.isEmpty(allRelations)) { + return new GeneralResult<>(true, null, "查询成功"); + } + // startRelations 是 根节点的数据集合。如果是正向的就取sourceid并去重,如果是反向就取targetid并去重 。后面生成的树就是以这些节点为根节点生成树的 + List startRelations = new ArrayList<>(); + if (config.getPathDirection()) { + // 拓扑路径和模型关系是相反的的即反向操作--获取树的根节点 + startRelations = allRelations.stream().filter(item -> config.getStartModuleId().equals(item.getTargetModuleId())).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InstanceRelation::getTargetInstanceId))), ArrayList::new)); + } else { + // 拓扑路径和模型关系是一致的即正向操作--获取树的根节点 + startRelations = allRelations.stream().filter(item -> config.getStartModuleId().equals(item.getSourceModuleId())).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InstanceRelation::getSourceInstanceId))), ArrayList::new)); + } + // 生成森林 + List trees = this.getTrees(startRelations, allRelations, moduleIds, config.getPathDirection()); + // 根据森林生成路径 + List> instancePaths = new ArrayList<>(); + for (InstanceRelation instanceRelation : trees) { + List> paths = GraphAlgorithmUtils.resourceInstanceAlgorithm(instanceRelation, config.getPathDirection()); + instancePaths.addAll(paths); + } + // 保证路径中节点数为拓扑指定的拓扑层级 + List> levelRelationList = instancePaths.stream().filter(item -> item.size() >= config.getTopologyLevel()).collect(Collectors.toList()); + return new GeneralResult<>(true, levelRelationList, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService getResourceData fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private List getTrees(List startRelations, List allRelations, List moduleIds, Boolean pathDirection) { + List relations = new ArrayList<>(); + // 循环的是根节点 + for (InstanceRelation startRelation : startRelations) { + InstanceRelation instanceRelation = new InstanceRelation(); + int i = 0; + List nextRelations = new ArrayList<>(); + if (pathDirection) { + // 拓扑路径和模型关系是相反的即反向操作---判断根节点下有没有对应的子节点 + nextRelations = allRelations.stream().filter(item -> item.getTargetModuleId().equals(moduleIds.get(i)) && item.getTargetInstanceId().equals(startRelation.getTargetInstanceId())).collect(Collectors.toList()); + } else { + // 拓扑路径和模型关系是一致的即正向操作--判断根节点下有没有对应的子节点 + nextRelations = allRelations.stream().filter(item -> item.getSourceModuleId().equals(moduleIds.get(i)) && item.getSourceInstanceId().equals(startRelation.getSourceInstanceId())).collect(Collectors.toList()); + } + if (CollectionUtils.isNotEmpty(nextRelations)) { + // 从这到this.getTreeByRecursion方法之前是设置的根节点的信息 + if (pathDirection) { + // 拓扑路径和模型关系是相反的即反向操作 + instanceRelation.setSourceInstanceId(startRelation.getTargetInstanceId()); + instanceRelation.setSourceInstanceName(startRelation.getTargetInstanceName()); + instanceRelation.setSourceModuleCode(startRelation.getTargetModuleCode()); + instanceRelation.setSourceModuleId(startRelation.getTargetModuleId()); + instanceRelation.setTargetInstanceId(startRelation.getSourceInstanceId()); + instanceRelation.setTargetInstanceName(startRelation.getSourceInstanceName()); + instanceRelation.setTargetModuleCode(startRelation.getSourceModuleCode()); + instanceRelation.setTargetModuleId(startRelation.getSourceModuleId()); + } else { + // 拓扑路径和模型关系是一致的即正向操作 + instanceRelation.setSourceInstanceId(startRelation.getSourceInstanceId()); + instanceRelation.setSourceInstanceName(startRelation.getSourceInstanceName()); + instanceRelation.setSourceModuleCode(startRelation.getSourceModuleCode()); + instanceRelation.setSourceModuleId(startRelation.getSourceModuleId()); + instanceRelation.setTargetInstanceId(startRelation.getTargetInstanceId()); + instanceRelation.setTargetInstanceName(startRelation.getTargetInstanceName()); + instanceRelation.setTargetModuleCode(startRelation.getTargetModuleCode()); + instanceRelation.setTargetModuleId(startRelation.getTargetModuleId()); + } + // 从这个开始是递归每个根节点的信息并生成树 + this.getTreeByRecursion(nextRelations, allRelations, moduleIds, i + 1, pathDirection); + instanceRelation.setCmdbInstanceRelations(nextRelations); + } + relations.add(instanceRelation); + } + return relations; + } + + private void getTreeByRecursion(List startRelations, List allRelations, List moduleIds, int i, Boolean pathDirection) { + for (InstanceRelation startRelation : startRelations) { + List nextRelations = new ArrayList<>(); + if (pathDirection) { + // 拓扑路径和模型关系是相反的即反向操作 + nextRelations = allRelations.stream().filter(item -> item.getTargetModuleId().equals(moduleIds.get(i)) && item.getTargetInstanceId().equals(startRelation.getSourceInstanceId())).collect(Collectors.toList()); + } else { + // 拓扑路径和模型关系是一致的即正向操作 + nextRelations = allRelations.stream().filter(item -> item.getSourceModuleId().equals(moduleIds.get(i)) && item.getSourceInstanceId().equals(startRelation.getTargetInstanceId())).collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(nextRelations)) { + continue; + } + startRelation.setCmdbInstanceRelations(nextRelations); + int j = i + 1; + if (j < moduleIds.size()) { + this.getTreeByRecursion(nextRelations, allRelations, moduleIds, j, pathDirection); + } + } + } + + /** + * @param id + * @return + */ + @Override + public GeneralResult> startModuleInstanceList(Long id) { + try { + List topologyModels = new ArrayList<>(); + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + CiModule module = moduleRepository.query(config.getStartModuleId()); + if (null == module) { + return new GeneralResult<>(false, "没有对应的起始模型!"); + } + // 将拓扑路径模型id类型转成Long类型 + List moduleIds = Arrays.asList(config.getTopologyPath().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + GeneralResult>> resourceData = this.getResourceData(config, moduleIds); + if (resourceData.isFailed()) { + return new GeneralResult<>(false, resourceData.getMessage()); + } + //获取拓扑路径对应的资源数据 + List> levelRelationList = resourceData.getData(); + if (CollectionUtils.isNotEmpty(levelRelationList)) { + //第一个就是起始模型数据 + levelRelationList.stream().flatMap(item -> item.stream()).filter(instanceModel -> instanceModel.getModuleId().equals(config.getStartModuleId())).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(InstanceModel::getInstanceId))), ArrayList::new)).forEach(item -> { + ResponseInstanceTopologyModel topologyModel = new ResponseInstanceTopologyModel(); + topologyModel.setCategoryId(config.getCategoryId()); + topologyModel.setStartModuleId(item.getModuleId()); + topologyModel.setStartModuleCode(item.getModuleCode()); + topologyModel.setInstanceId(item.getInstanceId()); + topologyModel.setInstanceName(item.getInstanceName()); + topologyModels.add(topologyModel); + }); + } + return new GeneralResult<>(true, topologyModels, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService startModuleInstanceList fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + /** + * 文件下载 + *

+ * 1. 创建excel对应的实体对象 + *

+ * 2. 设置返回的 参数 + *

+ * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大 + */ + @Override + public GeneralResult download(Long id, HttpServletResponse response) { + try { + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + String fileName = URLEncoder.encode(config.getName(), "UTF-8").replaceAll("\\+", "%20") + System.currentTimeMillis(); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + GeneralResult itemResult = this.searchItemList(id); + if (itemResult.isFailed()) { + return new GeneralResult<>(false, "下载失败"); + } + ColumnAndSearchItemModel data = itemResult.getData(); + List columns = data.getColumns(); + // 获取列名 + List> columnTest = this.columnData(columns); + Pager pager = new Pager(); + List params = new ArrayList<>(); + Param param = new Param(); + Map paramMap = new HashMap<>(); + paramMap.put("id", id); + param.setSign(Sign.EQ); + param.setParam(paramMap); + params.add(param); + pager.setParams(params); + pager.setPage(1); + pager.setRows(100000); + GeneralResult>> resourceResult = this.resourcelist(pager); + if (resourceResult.isFailed()) { + return new GeneralResult<>(false, "下载失败"); + } + List> rows = resourceResult.getData().getRows(); + // 获取数据 + List> lists = tableData(columns, rows); + EasyExcel.write(response.getOutputStream()).head(columnTest).sheet("模板").doWrite(lists); + return null; + } catch (Exception e) { + log.error("download is fail:", e); + return new GeneralResult<>(false, "下载失败"); + } + } + + /** + * 实例拓扑-全局拓扑 + * + * @param id + * @param instanceId + * @return + */ + @Override + public GeneralResult topoList(Long id, Long instanceId) { + try { + InstanceTopo topo = new InstanceTopo(); + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + CiModule startModule = moduleRepository.query(config.getStartModuleId()); + if (null == startModule) { + return new GeneralResult<>(false, "没有对应的起始模型数据"); + } + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null == relationCategory) { + return new GeneralResult<>(false, "没有对应的关系分组数据"); + } + List moduleRelations = moduleRelationRepository.queryModuleList(config.getCategoryId()); + if (CollectionUtils.isEmpty(moduleRelations)) { + return new GeneralResult<>(false, "对应的拓扑图内没有模型关系数据"); + } + Param param = new Param(); + Map paramMap = new HashMap<>(); + paramMap.put("id", id); + paramMap.put(startModule.getCode(), instanceId); + param.setParam(paramMap); + param.setSign(Sign.EQ); + List params = new ArrayList<>(); + params.add(param); + Pager pager = new Pager(1, Integer.MAX_VALUE, params, null); + // 获取到实例数据 + GeneralResult>> result = this.resourcelist(pager); + if (result.isFailed()) { + return new GeneralResult<>(false, "查询失败"); + } + if (CollectionUtils.isEmpty(result.getData().getRows())) { + return new GeneralResult<>(true, topo, "查询成功"); + } + // 获取实例数据 + List> datas = result.getData().getRows(); + // 将拓扑路径模型id类型转成Long类型 + List moduleIds = Arrays.asList(config.getTopologyPath().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + // 根据模型id查询模型信息 + List modules = moduleRepository.queryModuleListByIds(moduleIds); + if (CollectionUtils.isEmpty(modules)) { + return new GeneralResult<>(false, "没有对应的模型数据"); + } + // instancenodes中每条数据实际上在instance_relation_{code}表中都有一条数据与之对应 + List instancenodes = new ArrayList<>(); + Set sourceInstanceIds = new HashSet<>(); + Set targetInstanceIds = new HashSet<>(); + // 循环每行数据 + for (Map map : datas) { + // 循环拓扑路径 + for (int i = 0; i < modules.size() - 1; i++) { + InstanceNodeModel nodeModel = new InstanceNodeModel(); + nodeModel.setSourceModuleId(Long.valueOf(String.valueOf(map.get(modules.get(i).getCode() + "_moduleId")))); + nodeModel.setTargetModuleId(Long.valueOf(String.valueOf(map.get(modules.get(i + 1).getCode() + "_moduleId")))); + nodeModel.setSourceInstanceId(Long.valueOf(String.valueOf(map.get(modules.get(i).getCode() + "_instanceId")))); + nodeModel.setTargetInstanceId(Long.valueOf(String.valueOf(map.get(modules.get(i + 1).getCode() + "_instanceId")))); + // 去重-instancenodes集合中不存在才添加进去 + List nodeModels = instancenodes.stream().filter(item -> item.getSourceInstanceId().equals(nodeModel.getSourceInstanceId()) && item.getTargetInstanceId().equals(nodeModel.getTargetInstanceId()) && item.getSourceModuleId().equals(nodeModel.getSourceModuleId()) && item.getTargetModuleId().equals(nodeModel.getTargetModuleId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(nodeModels)) { + instancenodes.add(nodeModel); + sourceInstanceIds.add(nodeModel.getSourceInstanceId()); + targetInstanceIds.add(nodeModel.getTargetInstanceId()); + } + } + } + // 得到要查询的模型实例关系表名 + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(); + // 通过源实例id的集合和目的实例id的集合以及拓扑路径中模型id的集合 查询出大概范围的数据 + List instanceRelations = new ArrayList<>(); + if (config.getPathDirection()) { + instanceRelations = instanceRelationRepository.listReverse(relationTable, config.getCategoryId(), new ArrayList<>(targetInstanceIds), new ArrayList<>(sourceInstanceIds)); + } else { + instanceRelations = instanceRelationRepository.listForward(relationTable, config.getCategoryId(), new ArrayList<>(sourceInstanceIds), new ArrayList<>(targetInstanceIds)); + } + List links = new ArrayList<>(); + List nodes = new ArrayList<>(); + // java 处理精准匹配 + for (InstanceNodeModel nodeModel : instancenodes) { + InstanceRelation instanceRelation = new InstanceRelation(); + if (config.getPathDirection()) { + instanceRelation = instanceRelations.stream().filter(item -> item.getSourceInstanceId().equals(nodeModel.getTargetInstanceId()) && item.getTargetInstanceId().equals(nodeModel.getSourceInstanceId()) && item.getSourceModuleId().equals(nodeModel.getTargetModuleId()) && item.getTargetModuleId().equals(nodeModel.getSourceModuleId())).findFirst().orElse(null); + } else { + instanceRelation = instanceRelations.stream().filter(item -> item.getSourceInstanceId().equals(nodeModel.getSourceInstanceId()) && item.getTargetInstanceId().equals(nodeModel.getTargetInstanceId()) && item.getSourceModuleId().equals(nodeModel.getSourceModuleId()) && item.getTargetModuleId().equals(nodeModel.getTargetModuleId())).findFirst().orElse(null); + } + if (null != instanceRelation) { + InstanceRelationModel link = new InstanceRelationModel(); + Long moduleRelationId = instanceRelation.getModuleRelationId(); + ModuleRelation moduleRelation = moduleRelations.stream().filter(item -> item.getId().equals(moduleRelationId)).findFirst().orElse(null); + this.buildInstanceRelationModel(instanceRelation, link, moduleRelation); + links.add(link); + this.buildNodes(instanceRelation, nodes, modules); + } + } + topo.setNodes(nodes); + topo.setLinks(links); + return new GeneralResult<>(true, topo, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService topoList fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + @Override + public GeneralResult topology(Long id, Long instanceId) { + try { + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + CiModule startModule = moduleRepository.query(config.getStartModuleId()); + if (null == startModule) { + return new GeneralResult<>(false, "没有对应的起始模型数据"); + } + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null == relationCategory) { + return new GeneralResult<>(false, "没有对应的关系分组数据"); + } + List moduleRelations = moduleRelationRepository.queryModuleRealtionAndModuleImage(config.getCategoryId()); + if (CollectionUtils.isEmpty(moduleRelations)) { + return new GeneralResult<>(false, "对应的拓扑图内没有模型关系数据"); + } + //根据模型id去重 + ArrayList moduleRelationList = moduleRelations.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ModuleRelation::getModuleId))), ArrayList::new)); + //整理模型图标 + Map moduleRelationMap = moduleRelationList.stream().collect(Collectors.toMap(ModuleRelation::getModuleId, Function.identity())); + //获取实例数据 + Instance instance = instanceRepository.query(CmdbUtils.CMDB_INSTANCE + startModule.getCode().toLowerCase(), instanceId); + if (null == instance) { + return new GeneralResult<>(false, "资源实例数据不存在"); + } + List routeNodes = new ArrayList<>(); + //生产拓扑关系 + List nodes = Lists.newArrayList(); + //将当前节点放入 + InstanceModel instanceModel = new InstanceModel(); + instanceModel.setModuleId(startModule.getId()); + instanceModel.setModuleCode(startModule.getCode()); + instanceModel.setInstanceId(instanceId); + instanceModel.setInstanceName(instance.getName()); + instanceModel.setIconImage(startModule.getIconImage()); + nodes.add(instanceModel); + routeNodes.add(instanceModel); + List links = Lists.newArrayList(); + buildRelation(routeNodes, nodes, links, config, startModule.getId(), relationCategory, instance.getId(), 1, moduleRelationMap, config.getStartType()); + InstanceTopo topo = new InstanceTopo(); + topo.setNodes(nodes); + topo.setLinks(links); + return new GeneralResult<>(true, topo, "资源拓扑数据查询成功"); + } catch (Exception e) { + log.error("failed to query topology data:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void buildRelation(List routeNodes, List nodes, List links, TopologyConfig config, Long startModuleId, RelationCategory relationCategory, Long instanceId, int hierarchy, Map moduleRelationMap, String startType) throws Exception { + //当前当前实例节点所有的关系数据 + List instanceRelationsUp = Lists.newArrayList(); + List instanceRelationsDown = Lists.newArrayList(); + if ("UP".equalsIgnoreCase(startType)) { + List instanceRelations = instanceRelationRepository.queryTargets(CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(), startModuleId, instanceId); + instanceRelationsUp.addAll(instanceRelations); + } else if ("DOWN".equalsIgnoreCase(startType)) { + List instanceRelations = instanceRelationRepository.querySources(CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(), startModuleId, instanceId); + instanceRelationsDown.addAll(instanceRelations); + } else { + log.info("表名:{},源模型id:{},源实例id:{}", relationCategory.getCode().toLowerCase(), startModuleId, instanceId); + List up = instanceRelationRepository.queryTargets(CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(), startModuleId, instanceId); + List down = instanceRelationRepository.querySources(CmdbUtils.CMDB_INSTANCE_RELATION + relationCategory.getCode().toLowerCase(), startModuleId, instanceId); + instanceRelationsUp.addAll(up); + instanceRelationsDown.addAll(down); + } + log.info("查询到的上层关系数据:{}", JSON.toJSONString(instanceRelationsUp)); + log.info("查询到的下层关系数据:{}", JSON.toJSONString(instanceRelationsDown)); + if (instanceRelationsUp.isEmpty() && instanceRelationsDown.isEmpty()) { + log.info("向上或向下查询第" + hierarchy + "层结束"); + return; + } + if ("UP".equalsIgnoreCase(startType) && instanceRelationsUp.isEmpty()) { + log.info("向上查询第" + hierarchy + "层结束"); + return; + } + if ("DOWN".equalsIgnoreCase(startType) && instanceRelationsDown.isEmpty()) { + log.info("向下查询第" + hierarchy + "层结束"); + return; + } + log.info("当前模型[" + startModuleId + "],实例:[" + instanceId + "],向上查询到:[" + instanceRelationsUp.size() + "],目前在第" + hierarchy + "层"); + for (InstanceRelation instanceRelation : instanceRelationsUp) { + long count = routeNodes.stream().filter(item -> item.getModuleId().equals(instanceRelation.getSourceModuleId()) && item.getInstanceId().equals(instanceRelation.getSourceInstanceId())).count(); + //实例关系 + buildInstanceRelation(links, instanceRelation, relationCategory); + if (count > 0) { + continue; + } + //实例关系另一端的节点 + InstanceModel instanceModel = new InstanceModel(); + instanceModel.setModuleId(instanceRelation.getSourceModuleId()); + instanceModel.setModuleCode(instanceRelation.getSourceModuleCode()); + instanceModel.setInstanceId(instanceRelation.getSourceInstanceId()); + instanceModel.setInstanceName(instanceRelation.getSourceInstanceName()); + if (null == moduleRelationMap.get(instanceRelation.getSourceModuleId())) { + log.error("模型关系:{},实例关系{}", JSONObject.toJSON(moduleRelationMap), JSONObject.toJSON(instanceRelation)); + } + instanceModel.setIconImage(moduleRelationMap.get(instanceRelation.getSourceModuleId()).getIconImage()); + nodes.add(instanceModel); + routeNodes.add(instanceModel); + //向上查询 + if (hierarchy < config.getTopologyLevelUp()) { + buildRelation(routeNodes, nodes, links, config, instanceRelation.getSourceModuleId(), relationCategory, instanceRelation.getSourceInstanceId(), hierarchy + 1, moduleRelationMap, "UP"); + } + } + for (InstanceRelation instanceRelation : instanceRelationsDown) { + long count = routeNodes.stream().filter(item -> item.getModuleId().equals(instanceRelation.getTargetModuleId()) && item.getInstanceId().equals(instanceRelation.getTargetInstanceId())).count(); + //实例关系 + buildInstanceRelation(links, instanceRelation, relationCategory); + if (count > 0) { + continue; + } + //实例关系另一端的节点 + InstanceModel instanceModel = new InstanceModel(); + instanceModel.setModuleId(instanceRelation.getTargetModuleId()); + instanceModel.setModuleCode(instanceRelation.getTargetModuleCode()); + instanceModel.setInstanceId(instanceRelation.getTargetInstanceId()); + instanceModel.setInstanceName(instanceRelation.getTargetInstanceName()); + instanceModel.setIconImage(moduleRelationMap.get(instanceRelation.getTargetModuleId()).getIconImage()); + nodes.add(instanceModel); + routeNodes.add(instanceModel); + //向下查询 + if (hierarchy < config.getTopologyLevelDown()) { + buildRelation(routeNodes, nodes, links, config, instanceRelation.getTargetModuleId(), relationCategory, instanceRelation.getTargetInstanceId(), hierarchy + 1, moduleRelationMap, "DOWN"); + } + } + } + + private void buildInstanceRelation(List links, InstanceRelation instanceRelation, RelationCategory relationCategory) { + InstanceRelationModel instanceRelationModel = new InstanceRelationModel(); + instanceRelationModel.setId(instanceRelation.getId()); + instanceRelationModel.setRelationCategoryId(relationCategory.getId()); + instanceRelationModel.setRelationCategoryCode(relationCategory.getCode()); + instanceRelationModel.setRelationId(instanceRelation.getRelationId()); + instanceRelationModel.setRelationName(instanceRelation.getRelationName()); + instanceRelationModel.setSourceModuleId(instanceRelation.getSourceModuleId()); + instanceRelationModel.setSourceModuleCode(instanceRelation.getSourceModuleCode()); + instanceRelationModel.setSourceInstanceId(instanceRelation.getSourceInstanceId()); + instanceRelationModel.setSourceInstanceName(instanceRelation.getSourceInstanceName()); + instanceRelationModel.setTargetModuleId(instanceRelation.getTargetModuleId()); + instanceRelationModel.setTargetModuleCode(instanceRelation.getTargetModuleCode()); + instanceRelationModel.setTargetInstanceId(instanceRelation.getTargetInstanceId()); + instanceRelationModel.setTargetInstanceName(instanceRelation.getTargetInstanceName()); + instanceRelationModel.setType(instanceRelation.getSourceType() + "-" + instanceRelation.getTargetType()); + links.add(instanceRelationModel); + } + + + /** + * 实例拓扑-根据实例id查找下一层级实例拓扑 + * + * @param id + * @param instanceId + * @return + */ + @Override + public GeneralResult nextTopoList(Long id, Long moduleId, Long instanceId) { + try { + InstanceTopo topo = new InstanceTopo(); + TopologyConfig config = topologyConfigRepository.query(id); + if (null == config) { + return new GeneralResult<>(false, "没有对应的拓扑实例"); + } + List moduleRelations = moduleRelationRepository.queryModuleList(config.getCategoryId()); + if (CollectionUtils.isEmpty(moduleRelations)) { + return new GeneralResult<>(false, "对应的拓扑图内没有模型关系数据"); + } + RelationCategory category = relationCategoryRepository.query(config.getCategoryId()); + if (null == category) { + return new GeneralResult<>(false, "没有对应的关系分组数据"); + } + // 得到要查询的模型实例关系表名 + String relationTable = CmdbUtils.CMDB_INSTANCE_RELATION + category.getCode().toLowerCase(); + List instanceRelations = new ArrayList<>(); + List moduleIds = new ArrayList<>(); + if (null != config.getPathDirection()) { + if (config.getPathDirection()) { + instanceRelations = instanceRelationRepository.listReverseByInstanceIds(relationTable, config.getCategoryId(), moduleId, instanceId); + moduleIds = instanceRelations.stream().map(InstanceRelation::getSourceModuleId).collect(Collectors.toList()); + } else { + instanceRelations = instanceRelationRepository.listForwardByInstanceIds(relationTable, config.getCategoryId(), moduleId, instanceId); + moduleIds = instanceRelations.stream().map(InstanceRelation::getTargetModuleId).collect(Collectors.toList()); + } + } + if (CollectionUtils.isEmpty(instanceRelations)) { + return new GeneralResult<>(true, topo, "查询成功"); + } + moduleIds.add(moduleId); + // 根据模型id查询模型信息 + List modules = moduleRepository.queryModuleListByIds(moduleIds); + if (CollectionUtils.isEmpty(modules)) { + return new GeneralResult<>(false, "没有对应的模型数据"); + } + List links = new ArrayList<>(); + List nodes = new ArrayList<>(); + for (InstanceRelation instanceRelation : instanceRelations) { + InstanceRelationModel link = new InstanceRelationModel(); + Long moduleRelationId = instanceRelation.getModuleRelationId(); + ModuleRelation moduleRelation = moduleRelations.stream().filter(item -> item.getId().equals(moduleRelationId)).findFirst().orElse(null); + this.buildInstanceRelationModel(instanceRelation, link, moduleRelation); + links.add(link); + this.buildNodes(instanceRelation, nodes, modules); + } + topo.setNodes(nodes); + topo.setLinks(links); + return new GeneralResult<>(true, topo, "查询成功"); + } catch (Exception e) { + log.error("topologyConfigService nextTopoList fail:", e); + return new GeneralResult<>(false, "查询失败"); + } + } + + private void buildInstanceRelationModel(InstanceRelation instanceRelation, InstanceRelationModel link, ModuleRelation moduleRelation) { + if (instanceRelation.getIsReversed()) { + link.setRelationCategoryId(instanceRelation.getRelationCategoryId()); + link.setRelationCategoryCode(instanceRelation.getRelationCategoryCode()); + link.setRelationId(instanceRelation.getModuleRelationId()); + link.setRelationName(instanceRelation.getModuleRelationName()); + link.setSourceModuleId(instanceRelation.getTargetModuleId()); + link.setSourceModuleCode(instanceRelation.getTargetModuleCode()); + link.setSourceInstanceId(instanceRelation.getTargetInstanceId()); + link.setSourceInstanceName(instanceRelation.getTargetInstanceName()); + link.setTargetModuleId(instanceRelation.getSourceModuleId()); + link.setTargetModuleCode(instanceRelation.getSourceModuleCode()); + link.setTargetInstanceId(instanceRelation.getSourceInstanceId()); + link.setTargetInstanceName(instanceRelation.getSourceInstanceName()); + link.setType(moduleRelation.getTargetType() + "-" + moduleRelation.getSourceType()); + } else { + BeanUtils.copyProperties(instanceRelation, link); + link.setRelationId(instanceRelation.getModuleRelationId()); + link.setRelationName(instanceRelation.getModuleRelationName()); + link.setType(moduleRelation.getSourceType() + "-" + moduleRelation.getTargetType()); + } + } + + private void buildNodes(InstanceRelation instanceRelation, List nodes, List modules) { + // 获取节点数据 + // 去重-因为不同的模型对应的实例的id有可能重复。所以要对实例去重的话必须用模型id和实例id一起去重 + List instanceModelList = nodes.stream().filter(item -> item.getModuleId().equals(instanceRelation.getSourceModuleId()) && item.getInstanceId().equals(instanceRelation.getSourceInstanceId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(instanceModelList)) { + InstanceModel source = new InstanceModel(); + source.setModuleId(instanceRelation.getSourceModuleId()); + source.setModuleCode(instanceRelation.getSourceModuleCode()); + source.setInstanceId(instanceRelation.getSourceInstanceId()); + source.setInstanceName(instanceRelation.getSourceInstanceName()); + CiModule module = modules.stream().filter(item -> item.getId().equals(source.getModuleId())).findFirst().orElse(null); + source.setIconImage(module.getIconImage()); + nodes.add(source); + } + List instanceModels = nodes.stream().filter(item -> item.getModuleId().equals(instanceRelation.getTargetModuleId()) && item.getInstanceId().equals(instanceRelation.getTargetInstanceId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(instanceModels)) { + InstanceModel target = new InstanceModel(); + target.setModuleId(instanceRelation.getTargetModuleId()); + target.setModuleCode(instanceRelation.getTargetModuleCode()); + target.setInstanceId(instanceRelation.getTargetInstanceId()); + target.setInstanceName(instanceRelation.getTargetInstanceName()); + CiModule module = modules.stream().filter(item -> item.getId().equals(target.getModuleId())).findFirst().orElse(null); + target.setIconImage(module.getIconImage()); + nodes.add(target); + } + } + + /** + * 获取起始模型为源id,对应的路径。 + * + * @param topologyModel + * @return + */ + private GeneralResult>>> checkData(RequestInstanceTopologyModel topologyModel) { + try { + if (null == topologyModel.getCategoryId()) { + return new GeneralResult<>(false, "categoryId参数不能为空"); + } + if (null == topologyModel.getStartModuleId()) { + return new GeneralResult<>(false, "startModuleId参数不能为空"); + } + // 根据拓扑图分组id查询分组内模型数据 + List relations = moduleRelationRepository.queryModuleList(topologyModel.getCategoryId()); + if (CollectionUtils.isEmpty(relations)) { + return new GeneralResult<>(false, "拓扑图内无拓扑模型!"); + } + // 情况一:以startModuleId为源id获取对应的树 并 获取对应路径集合 + List> outDegreePath = this.getTreePath(topologyModel, relations, true); + // 情况二:以startModuleId为目的id获取对应的树 并 获取对应路径集合 + List> penetrationPath = this.getTreePath(topologyModel, relations, false); + Map>> map = new HashMap(); + map.put(true, penetrationPath); + map.put(false, outDegreePath); + return new GeneralResult<>(true, map, "拓扑图内无拓扑模型!"); + } catch (Exception e) { + e.printStackTrace(); + return new GeneralResult<>(false, "参数校验失败"); + } + } + + private String escapeData(TopologyConfig config) { + try { + // 获取拓扑路径模型id + // 将拓扑路径模型id类型转成Long类型 + List moduleIds = Arrays.asList(config.getTopologyPath().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + // 根据模型id查询模型信息 + List modules = moduleRepository.queryModuleListByIds(moduleIds); + if (CollectionUtils.isEmpty(modules)) { + return "没有对应的模型数据"; + } + String pathName = modules.stream().map(CiModule::getName).collect(Collectors.joining("-")); + config.setTopologyPathName(pathName); + RelationCategory relationCategory = relationCategoryRepository.query(config.getCategoryId()); + if (null == relationCategory) { + return "没有对应的关联分组数据"; + } + config.setCategoryName(relationCategory.getName()); + CiModule startModule = moduleRepository.query(config.getStartModuleId()); + if (null == startModule) { + return "没有对应的起始模型数据"; + } + if (null != config.getIgnoreModuleIds()) { + List ignoreIds = Arrays.asList(config.getIgnoreModuleIds().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + List ignores = moduleRepository.queryModuleListByIds(ignoreIds); + for (Long moduleId : ignoreIds) { + CiModule module = ignores.stream().filter(item -> item.getId().equals(moduleId)).findFirst().orElse(null); + if (null == module) { + return "没有对应的忽略模型数据"; + } + } + config.setIgnoreModuleId(ignoreIds); + } + if (null != config.getWayModuleIds()) { + List wayIds = Arrays.asList(config.getWayModuleIds().split(",")).stream().map(moduleId -> Long.parseLong(moduleId)).collect(Collectors.toList()); + List ways = moduleRepository.queryModuleListByIds(wayIds); + for (Long moduleId : wayIds) { + CiModule module = ways.stream().filter(item -> item.getId().equals(moduleId)).findFirst().orElse(null); + if (null == module) { + return "没有对应的忽略模型数据"; + } + } + config.setWayModuleId(wayIds); + } + config.setStartModuleName(startModule.getName()); + return null; + } catch (Exception e) { + return "数据库查询出错"; + } + } + + /** + * 根据predicate生成出度树或者入度树并得到起路径: + *

+ * 生成出度树 并 获取对应路径 + * 实现逻辑:这里是以sourceId为key进行分组的并用startModuleId匹配sourceId生成对应的树的。 + * 这里就是以startModuleId作为源id(sourceId)获取对应的树。 + *

+ * 生成入度树 并 获取对应路径 + * 实现逻辑:这里是以targetId为key进行分组的并用startModuleId匹配targetId生成对应的树的。 + * 在数据结构上看就是以startModuleId为目的id(targetId)获取相应的额树。 + * + * @param topologyModel + * @param relations + * @return + */ + private List> getTreePath(RequestInstanceTopologyModel topologyModel, List relations, Boolean predicate) { + ModuleRelation treePath = new ModuleRelation(); + Map> relationMap = relations.stream().collect(Collectors.groupingBy(predicate ? ModuleRelation::getSourceId : ModuleRelation::getTargetId)); + List moduleRelations = relationMap.get(topologyModel.getStartModuleId()); + if (CollectionUtils.isNotEmpty(moduleRelations)) { + if (predicate) { + treePath.setSourceId(topologyModel.getStartModuleId()); + } else { + treePath.setTargetId(topologyModel.getStartModuleId()); + } + //把遍历过的路径存入到集合中 + List> lineList = new ArrayList<>(); + for (ModuleRelation moduleRelation : moduleRelations) { + Map map = new HashMap<>(); + if (predicate) { + map.put(moduleRelation.getSourceId(), moduleRelation.getTargetId()); + } else { + map.put(moduleRelation.getTargetId(), moduleRelation.getSourceId()); + } + lineList.add(map); + } + //递归生成对应的树 + this.recursionTree(moduleRelations, relationMap, lineList, predicate); + treePath.setCmdbModuleRelationList(moduleRelations); + } else { + return new ArrayList<>(); + } + if (predicate) { + //根据生成树获取树的所有路径 + return GraphAlgorithmUtils.outDegreeGraphAlgorithm(treePath); + } else { + //根据生成树获取对应路径 + return GraphAlgorithmUtils.penetrationGraphAlgorithm(treePath); + } + } + + /** + * 此处就是递归生成对应的树 + * + * @param relations + * @param relationMap + */ + private void recursionTree(List relations, Map> relationMap, List> lineList, Boolean predicate) { + for (ModuleRelation moduleRelation : relations) { + List moduleRelations = relationMap.get(predicate ? moduleRelation.getTargetId() : moduleRelation.getSourceId()); + if (CollectionUtils.isEmpty(moduleRelations)) { + continue; + } + List moduleRelationList = new ArrayList<>(); + for (ModuleRelation relation : moduleRelations) { + //1:判断这个路径是是否已经遍历过了(路径就是线段,是不区分弧头和弧尾的。所以说 需要用 头结点-尾结点 以及 尾结点-头结点 去判断这条路径是否存在) + Map map = lineList.stream().filter(item -> relation.getTargetId().equals(item.get(relation.getSourceId())) || relation.getSourceId().equals(item.get(relation.getTargetId()))).findFirst().orElse(null); + //2:判断如果尾结点是走过路径的头结点也是不行的。 + Map longMap = lineList.stream().filter(item -> item.containsKey(predicate ? relation.getTargetId() : relation.getSourceId())).findFirst().orElse(null); + if (MapUtils.isEmpty(map) && MapUtils.isEmpty(longMap)) { + moduleRelationList.add(relation); + Map hashMap = new HashMap<>(); + hashMap.put(predicate ? relation.getSourceId() : relation.getTargetId(), predicate ? relation.getTargetId() : relation.getSourceId()); + lineList.add(hashMap); + } + } + if (CollectionUtils.isNotEmpty(moduleRelationList)) { + moduleRelation.setCmdbModuleRelationList(moduleRelationList); + this.recursionTree(moduleRelationList, relationMap, lineList, predicate); + } + } + } + + /** + * 获取路径 + * + * @param allList + * @param modules + * @param topologyLevel 拓扑层级 + * @param pathModels + * @param pathDirection + */ + private void getPathModelList(List> allList, List modules, Integer topologyLevel, List pathModels, Boolean pathDirection, RequestInstanceTopologyModel topologyModel) { + List> treePath = allList.stream().filter(item -> item.size() >= topologyLevel).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(treePath)) { + log.info("treePath:{}", JSON.toJSONString(treePath)); + List> moduleList = new ArrayList<>(); + for (List ids : treePath) { + ids.removeAll(Collections.singleton(null)); + // 应该是 一个一个id 去找对应的模型 并 add对应的模型分组中 (一个一个的匹配是为了保证节点的顺序性不被打乱) + List list = new ArrayList<>(); + for (Long id : ids) { + CiModule module = modules.stream().filter(item -> id.equals(item.getId())).findFirst().orElse(null); + if (null != module) { + list.add(module); + } + } + moduleList.add(list); + } + for (List list : moduleList) { + if (list.size() >= topologyLevel) { + //截取前topologyLevel个数据 + List modulesData = list.subList(0, topologyLevel); + //过滤忽略模型 + if (CollectionUtils.isNotEmpty(topologyModel.getIgnoreModuleId())) { + List modulesDataList = modulesData.stream().filter(item -> topologyModel.getIgnoreModuleId().contains(item.getId())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(modulesDataList)) { + continue; + } + } + if (CollectionUtils.isNotEmpty(topologyModel.getWayModuleId())) { + //判断是否存在必经模型.containsAll + boolean containsAll = modulesData.stream().map(CiModule::getId).collect(Collectors.toList()).containsAll(topologyModel.getWayModuleId()); + if (!containsAll) { + continue; + } + } + PathModel pathModel = new PathModel(); + String pathName = modulesData.stream().map(CiModule::getName).collect(Collectors.joining("-")); + String path = modulesData.stream().map(CiModule::getId).map(item -> String.valueOf(item)).collect(Collectors.joining(",")); + pathModel.setTopologyPathName(pathName); + pathModel.setTopologyPath(path); + pathModel.setPathDirection(pathDirection); + pathModels.add(pathModel); + } + } + } + } + + private List> pagerFilter(List> relationList, Pager pager) { + List> instanceIdRelations = new ArrayList<>(); + // 如果传过来的pager参数为空就不需要过滤了 直接返回 + if (CollectionUtils.isEmpty(pager.getParams()) || MapUtils.isEmpty(pager.getParams().get(0).getParam())) { + return relationList; + } + Map param = pager.getParams().get(0).getParam(); + param.remove("id"); + // 外循环是循环每一行数据 + for (List relationModels : relationList) { + boolean flag = true; + // 内循环是循环每一行数据中的每个对象 + for (InstanceModel relationModel : relationModels) { + if (param.containsKey(relationModel.getModuleCode())) { + if (!relationModel.getInstanceId().equals(Long.valueOf(String.valueOf(param.get(relationModel.getModuleCode()))))) { + flag = false; + break; + } + } + } + if (flag) { + instanceIdRelations.add(relationModels); + } + } + return instanceIdRelations; + } + + /** + * 获取动态表头 + * + * @param columns + * @return + */ + private List> columnData(List columns) { + List> labelList = new ArrayList<>(); + for (ColumnModel column : columns) { + List list = new ArrayList<>(); + list.add(column.getLabel()); + labelList.add(list); + } + return labelList; + } + + /** + * 根据动态表头匹配对应列数据 + * + * @param columns + * @param rows + * @return + */ + private List> tableData(List columns, List> rows) { + // 对于每一行数据找匹配到对应的列上 + List> list = ListUtils.newArrayList(); + for (Map map : rows) { + List data = ListUtils.newArrayList(); + // 对于每行数据匹配到对应的列上 + for (ColumnModel column : columns) { + String value = column.getProp(); + Object object = map.get(value); + data.add(object); + } + list.add(data); + } + return list; + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/InstanceRelationTask.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/InstanceRelationTask.java new file mode 100644 index 0000000..9068bfc --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/InstanceRelationTask.java @@ -0,0 +1,1126 @@ +package com.bocloud.ams.service.task; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.InstanceRelationHistoryAlterModel; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.instance.InstanceRelationHistoryRecordRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.utils.AutoModuleInstanceRelationUtils; +import com.bocloud.ams.service.utils.ModuleConstant; +import com.bocloud.ams.service.utils.RelationHistoryConstant; +import com.bocloud.ams.service.utils.RepositoryHandler; + +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.Assert; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @Description: 单实例自动关联任务 + * @Title: InstanceRelationTask + * @Author: majiali + * @CreateTime: 2022/6/9 15:09 + */ +@Slf4j +public class InstanceRelationTask implements Runnable { + + private AutoRelationRule relationRule; + private ModuleRelation moduleRelation; + private InstanceRelationRepository instanceRelationRepository; + private InstanceRepository instanceRepository; + private InstanceValueRepository instanceValueRepository; + private InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository; + private RepositoryHandler handler; + private Instance instance; + private Long userId; + private LockFactory lockFactory; + private OperationalAuditService operationalAuditService; + private OperationalAuditRepository operationalAuditRepository; + + public InstanceRelationTask(AutoRelationRule relationRule, ModuleRelation moduleRelation, + InstanceRelationRepository instanceRelationRepository, InstanceRepository instanceRepository, + InstanceValueRepository instanceValueRepository, + InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository, RepositoryHandler handler, + Instance instance, Long userId, LockFactory lockFactory , OperationalAuditService operationalAuditService,OperationalAuditRepository operationalAuditRepository) { + this.relationRule = relationRule; + this.moduleRelation = moduleRelation; + this.instanceRelationRepository = instanceRelationRepository; + this.instanceRepository = instanceRepository; + this.instanceValueRepository = instanceValueRepository; + this.instanceValueRepository = instanceValueRepository; + this.instanceRelationHistoryRecordRepository = instanceRelationHistoryRecordRepository; + this.handler = handler; + this.instance = instance; + this.userId = userId; + this.lockFactory = lockFactory; + this.operationalAuditService = operationalAuditService; + this.operationalAuditRepository = operationalAuditRepository; + } + + @SneakyThrows + @Override + public void run() { + log.info("开始处理单实例关系任务,实例【{}】,模型关系【{}】", instance, moduleRelation); + String path = "auto_relatiom_module_relation_id_" + moduleRelation.getId() + "_instance_id_" + instance.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + // 实例模型为源模型,则查询目标模型实例挂关系-正向关系 + if (instance.getModuleId().equals(moduleRelation.getSourceId())) { + log.info("实例模型为源模型,查询目标模型实例挂关系-正向关系"); + // 根据目标模型查询模型实例数据 + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getTargetCode().toLowerCase(); + List targetInstance = + instanceRepository.queryByModuleId(instanceTable, moduleRelation.getTargetId()); + // 查询实例的所有数据 + buildInstanceData(targetInstance, moduleRelation.getTargetCode()); + // 处理当前实例,与目标实例的关系 + dealPositiveInstanceRelation(instance, targetInstance, moduleRelation, relationRule, userId); + } else { + log.info("实例模型为目标模型,查询源模型实例挂关系-反向关系"); + // 实例模型为目标模型,则查询源模型实例挂关系 + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getSourceCode().toLowerCase(); + List targetInstance = + instanceRepository.queryByModuleId(instanceTable, moduleRelation.getSourceId()); + // 查询实例的所有数据 + buildInstanceData(targetInstance, moduleRelation.getSourceCode()); + dealReverseInstanceRelation(instance, targetInstance, moduleRelation, relationRule, userId); + } + + } catch (Exception e) { + log.error("单实例关系自动关联失败", e); + } + log.info("结束单实例关系任务"); + } + + /** + * @param sourceInstance 当前实例信息(源) + * @param targetInstances 目标实例 + * @param moduleRelation 模型关系 + * @param relationRule 关联规则 + * @Description:处理正向关系 + * @Author majiali + * @CreateTime 2022/5/20 16:35 + */ + private void dealPositiveInstanceRelation(Instance sourceInstance, List targetInstances, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + + log.info("开始处理实例关系,当实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + // 有关系目标实例id + Map targetRelationMap = new HashMap<>(); + // 实例模型为源模型,则查询目标模型实例挂关系 + for (Instance target : targetInstances) { + boolean flag = AutoModuleInstanceRelationUtils.isInstanceRelation(sourceInstance, target, relationRule); + if (flag) { + targetRelationMap.put(target.getId(), target); + } + } + if (!targetRelationMap.isEmpty()) { + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + // 1-1 1-N N-1 N-N 关系校验 + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存一条记录 判断源实例是否有关系记录,同时判断目标实例是否已经有其他实例关系 + deal11PositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存全部记录 + deal1NPositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存一条记录 + dealN1PositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存全部记录 + dealNNPositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } + } else { + log.info("没有满足规则的实例数据,删除表中已有实例关系"); + deletePositiveRelation(sourceInstance, moduleRelation, userId); + + } + log.info("结束处理实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向1-1关系 + * @CreateTime 2022/5/26 16:28 + */ + private void deal11PositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向1-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getTargetInstanceId()) + && !item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getTargetInstanceId)); + } + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + // 判断当前目标实例中是否有被占用的 + // 剩余满足条件且目标实例被使用的原实例关系 + if (relationIds.size() == 1 && CollectionUtils.isEmpty(oldConflictRelations)) { + Instance targetInstance = targetRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + // 不满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + if (CollectionUtils.isNotEmpty(relations)) { + conflictRelations.addAll(relations); + } + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + + if (relationIds.size() == 0 && oldKeepRelations.size() == 1) { + InstanceRelation relation = oldKeepRelations.get(0); + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向1-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向1-N关系 + * @CreateTime 2022/5/26 16:28 + */ + private void deal1NPositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向1-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getTargetInstanceId()) + && !item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getTargetInstanceId)); + } + // 实例关系 + List relationList = new ArrayList<>(); + for (Long id : relationIds) { + List conflicts = conflictRelationMap.get(id); + if (CollectionUtils.isEmpty(conflicts)) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetRelationMap.get(id), moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } else { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflicts)); + } + } + //数据库中已有满足关联规则的关系,校验被关联方是否满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向1-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向N-1关系 + * @CreateTime 2022/5/26 16:28 + */ + private void dealN1PositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向N-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + if (relationIds.size() == 1) { + Instance targetInstance = targetRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + // 不满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, Arrays.asList(relation))); + } + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向N-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向N-N关系 + * @CreateTime 2022/5/26 16:28 + */ + private void dealNNPositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向N-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + // 实例关系 + List relationList = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + for (Long id : relationIds) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetRelationMap.get(id), moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.RELATION.getValue(), + userId, null)); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向N-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * 构建实例数据 + * + * @param targetInstance + * @param moduleCode + * @throws Exception + */ + private void buildInstanceData(List targetInstance, String moduleCode) throws Exception { + for (Instance instance : targetInstance) { + // 查询实例数据 + List instanceValues = instanceValueRepository.listByInstanceId(instance.getId(), + CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase()); + instance.setInstanceValues(instanceValues); + } + } + + /** + * @param targetInstance 当前实例信息(目标) + * @param sourceInstances 源实例 + * @param moduleRelation 模型关系 + * @param relationRule 关联规则 + * @Description:处理反向关系 + * @Author majiali + * @CreateTime 2022/5/20 16:35 + */ + private void dealReverseInstanceRelation(Instance targetInstance, List sourceInstances, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + + log.info("开始处理实例关系,当实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + // 有关系目标实例id + Map sourceRelationMap = new HashMap<>(); + // 实例模型为目标模型,则查询源模型实例挂关系 + for (Instance source : sourceInstances) { + boolean flag = AutoModuleInstanceRelationUtils.isInstanceRelation(source, targetInstance, relationRule); + if (flag) { + sourceRelationMap.put(source.getId(), source); + } + } + // 关联关系的优先级 手动关联、自动关联,规则更改后,是否要更新关联关系? + if (!sourceRelationMap.isEmpty()) { + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + // 1-1 1-N N-1 N-N 关系校验 + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存一条记录 + deal11ReverseRelation(targetInstance, sourceRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存一条记录 + deal1NReverseRelation(targetInstance, sourceRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存全部记录 + dealN1ReverseRelation(targetInstance, sourceRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存全部记录 + dealNNReverseRelation(targetInstance, sourceRelationMap, moduleRelation, relationRule, userId); + } + } else { + log.info("没有满足规则的实例数据,删除表中已有实例关系"); + deleteReverseRelation(targetInstance, moduleRelation, userId); + } + log.info("结束处理实例关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param targetInstance 目标实例 + * @param sourceRelationMap 满足规则的源实例 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 反向1-1关系 + * @CreateTime 2022/5/26 16:28 + */ + private void deal11ReverseRelation(Instance targetInstance, Map sourceRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理反向1-1关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(sourceRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getSourceInstanceId()) + && !item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getSourceInstanceId)); + } + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList())); + // 关联历史 + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + // 判断当前源实例中是否有被占用的 + // 剩余满足条件源实例被使用的原实例关系 + if (relationIds.size() == 1 && CollectionUtils.isEmpty(oldConflictRelations)) { + Instance sourceInstance = sourceRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + + for (Long id : relationIds) { + list.add( + AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + // 不满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + List relations = conflictRelationMap.get(relation.getSourceInstanceId()); + if (CollectionUtils.isNotEmpty(relations)) { + conflictRelations.addAll(relations); + } + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceRelationMap.get(relation.getSourceInstanceId()), targetInstance, moduleRelation, + relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + for (Long id : relationIds) { + list.add( + AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + + if (relationIds.size() == 0 && oldKeepRelations.size() == 1) { + InstanceRelation relation = oldKeepRelations.get(0); + List relations = conflictRelationMap.get(relation.getSourceInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceRelationMap.get(relation.getSourceInstanceId()), targetInstance, moduleRelation, + relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + + } + + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, null, targetInstance, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理反向1-1关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param targetInstance 目标实例 + * @param sourceRelationMap 满足规则的源实例 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 反向1-N关系 当前实例为目标实例,一个目标实例只能对应一个源实例 + * @CreateTime 2022/5/26 16:28 + */ + private void deal1NReverseRelation(Instance targetInstance, Map sourceRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理反向1-N关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(sourceRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList())); + // 关联历史 + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + if (relationIds.size() == 1) { + Instance sourceInstance = sourceRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + for (Long id : relationIds) { + list.add( + AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + for (InstanceRelation relation : oldKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceRelationMap.get(relation.getSourceInstanceId()), targetInstance, moduleRelation, + relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, Arrays.asList(relation))); + } + for (Long id : relationIds) { + list.add( + AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, null, targetInstance, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理反向1-N关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param targetInstance 目标实例 + * @param sourceRelationMap 满足规则的源实例 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 反向N-1关系 当前实例为目标实例,一个目标实例只能对应一个源实例 + * @CreateTime 2022/5/26 16:28 + */ + private void dealN1ReverseRelation(Instance targetInstance, Map sourceRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理反向N-1关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(sourceRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldTargetRelations = oldRelations.stream() + .filter(item -> item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldTargetRelations.stream() + .filter(item -> relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldTargetRelations.stream() + .filter(item -> !relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList())); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getSourceInstanceId()) + && !item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getSourceInstanceId)); + } + // 执行历史 + List list = new ArrayList<>(); + // 实例关系 + List relationList = new ArrayList<>(); + for (Long id : relationIds) { + List conflicts = conflictRelationMap.get(id); + if (CollectionUtils.isEmpty(conflicts)) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceRelationMap.get(id), + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.RELATION.getValue(), + userId, null)); + } else { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflicts)); + } + } + + //数据库中已有满足关联规则的关系,校验被关联方是否满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List relations = conflictRelationMap.get(relation.getSourceInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, + sourceRelationMap.get(relation.getSourceInstanceId()), targetInstance, moduleRelation, + relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, null, targetInstance, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理反向N-1关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param targetInstance 目标实例 + * @param sourceRelationMap 满足规则的源实例 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 反向N-N关系 + * @CreateTime 2022/5/26 16:28 + */ + private void dealNNReverseRelation(Instance targetInstance, Map sourceRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理反向N-N关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(sourceRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getTargetInstanceId().equals(targetInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getSourceInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getSourceInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + // 实例关系 + List relationList = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, null, targetInstance, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + for (Long id : relationIds) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceRelationMap.get(id), + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, sourceRelationMap.get(id), + targetInstance, moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.RELATION.getValue(), + userId, null)); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束反向N-N关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + private void deletePositiveRelation(Instance sourceInstance, + ModuleRelation moduleRelation, Long userId) throws Exception { + log.info("开始处理正向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), sourceInstance.getId(), moduleRelation.getTargetId(), null); + if (CollectionUtils.isNotEmpty(oldRelations)) { + log.info("删除库中已有的实例关系,数量:{}", oldRelations.size()); + // 执行历史 + List list = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + private void deleteReverseRelation(Instance targetInstance, + ModuleRelation moduleRelation, Long userId) throws Exception { + log.info("开始处理反向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), targetInstance.getId()); + if (CollectionUtils.isNotEmpty(oldRelations)) { + log.info("删除库中已有的实例关系,数量:{}", oldRelations.size()); + // 执行历史 + List list = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(false, null, targetInstance, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理反向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", targetInstance.getId(), targetInstance.getModuleCode(), + moduleRelation.getId()); + } + + //操作审计 + private void addOperationalAudit(List list,Long userId) { + try { + List auditList = new ArrayList<>(); + for (InstanceRelationHistoryRecord historyRecord : list) { + + if(!RelationHistoryConstant.Status.SUCCESS.getValue().equals(historyRecord.getStatus())){ + continue; + } + String props = historyRecord.getProps(); + //关联 + InstanceRelationHistoryAlterModel alter = null; + if (StringUtils.isNotEmpty(props)) { + alter = JSONObject.parseObject(historyRecord.getProps(), InstanceRelationHistoryAlterModel.class); + } + //关联 + Map afterMap = null; + Map beforeMap = null; + OperationalAudit audit = null; + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(historyRecord.getType())) { + + if (null != alter && CollectionUtils.isNotEmpty(alter.getBefore())) { + beforeMap = JSON.parseObject(JSON.toJSONString(alter.getBefore().get(0)), new TypeReference>() { + }); + } + audit = operationalAuditService.buildLog(OperationalAuditType.ASSOCIATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getInstanceId(), userId, beforeMap, afterMap); + + } else { + if (null != alter && null != alter.getAfter()) { + afterMap = + JSON.parseObject(JSON.toJSONString(alter.getAfter()), new TypeReference>() { + }); + } + + audit = operationalAuditService.buildLog(OperationalAuditType.RELATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getInstanceId(), userId, beforeMap, afterMap); + } + + auditList.add(audit); + } + + if(!auditList.isEmpty()){ + operationalAuditRepository.batchSave(auditList, 100); + } + + }catch (Exception e){ + log.error("记录操作审计信息异常",e); + } + + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/ModuleInstanceRelationTask.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/ModuleInstanceRelationTask.java new file mode 100644 index 0000000..edb6f6d --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/task/ModuleInstanceRelationTask.java @@ -0,0 +1,649 @@ +package com.bocloud.ams.service.task; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.audit.OperationalAudit; +import com.bocloud.ams.entity.enums.OperationalAuditType; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.InstanceRelationHistoryAlterModel; +import com.bocloud.ams.entity.module.ModuleRelation; +import com.bocloud.ams.repository.audit.OperationalAuditRepository; +import com.bocloud.ams.repository.instance.InstanceRelationHistoryRecordRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.audit.OperationalAuditService; +import com.bocloud.ams.service.utils.AutoModuleInstanceRelationUtils; +import com.bocloud.ams.service.utils.ModuleConstant; +import com.bocloud.ams.service.utils.RelationHistoryConstant; +import com.bocloud.ams.service.utils.RepositoryHandler; + +import com.megatron.framework.lock.AutoCloseLock; +import com.megatron.framework.lock.LockFactory; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.Assert; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @Description: 模型实例自动关联任务 + * @Title: ModuleInstanceRelationTask + * @Author: majiali + * @CreateTime: 2022/6/9 15:09 + */ +@Slf4j +public class ModuleInstanceRelationTask implements Runnable { + + private AutoRelationRule relationRule; + private ModuleRelation moduleRelation; + private InstanceRelationRepository instanceRelationRepository; + private InstanceRepository instanceRepository; + private InstanceValueRepository instanceValueRepository; + private InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository; + private RepositoryHandler handler; + private LockFactory lockFactory; + private OperationalAuditService operationalAuditService; + private OperationalAuditRepository operationalAuditRepository; + + public ModuleInstanceRelationTask(AutoRelationRule relationRule, ModuleRelation moduleRelation, + InstanceRelationRepository instanceRelationRepository, InstanceRepository instanceRepository, + InstanceValueRepository instanceValueRepository, + InstanceRelationHistoryRecordRepository instanceRelationHistoryRecordRepository, RepositoryHandler handler, + LockFactory lockFactory, OperationalAuditService operationalAuditService,OperationalAuditRepository operationalAuditRepository) { + this.relationRule = relationRule; + this.moduleRelation = moduleRelation; + this.instanceRelationRepository = instanceRelationRepository; + this.instanceRepository = instanceRepository; + this.instanceValueRepository = instanceValueRepository; + this.instanceValueRepository = instanceValueRepository; + this.instanceRelationHistoryRecordRepository = instanceRelationHistoryRecordRepository; + this.handler = handler; + this.lockFactory = lockFactory; + this.operationalAuditService = operationalAuditService; + this.operationalAuditRepository = operationalAuditRepository; + + } + + @SneakyThrows + @Override + public void run() { + log.info("开始处理模型实例关系,模型关系id:{}", moduleRelation.getId()); + String path = "auto_relatiom_module_relation_id_" + moduleRelation.getId(); + try (AutoCloseLock lock = lockFactory.getACLock(path)) { + Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时"); + String sourceInstanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getSourceCode().toLowerCase(); + List sourceInstances = + instanceRepository.queryByModuleId(sourceInstanceTable, moduleRelation.getSourceId()); + buildInstanceData(sourceInstances, moduleRelation.getSourceCode()); + // 根据目标模型查询模型实例数据 + String instanceTable = CmdbUtils.CMDB_INSTANCE + moduleRelation.getTargetCode().toLowerCase(); + List targetInstances = + instanceRepository.queryByModuleId(instanceTable, moduleRelation.getTargetId()); + buildInstanceData(targetInstances, moduleRelation.getTargetCode()); + if (CollectionUtils.isNotEmpty(sourceInstances) && CollectionUtils.isNotEmpty(targetInstances)) { + for (Instance instance : sourceInstances) { + // 处理当前实例,与目标实例的关系 + dealPositiveInstanceRelation(instance, targetInstances, moduleRelation, relationRule, 1L); + } + } + } catch (Exception e) { + log.error("模型实例自动关联失败", e); + } + log.info("结束模型实例关系,模型关系id:{}", moduleRelation.getId()); + + } + + /** + * @param sourceInstance 当前实例信息(源) + * @param targetInstances 目标实例 + * @param moduleRelation 模型关系 + * @param relationRule 关联规则 + * @Description:处理正向关系 + * @Author majiali + * @CreateTime 2022/5/20 16:35 + */ + private void dealPositiveInstanceRelation(Instance sourceInstance, List targetInstances, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + + log.info("开始处理实例关系,当实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + // 有关系目标实例id + Map targetRelationMap = new HashMap<>(); + // 实例模型为源模型,则查询目标模型实例挂关系 + for (Instance target : targetInstances) { + boolean flag = AutoModuleInstanceRelationUtils.isInstanceRelation(sourceInstance, target, relationRule); + if (flag) { + targetRelationMap.put(target.getId(), target); + } + } + if (!targetRelationMap.isEmpty()) { + String sourceType = moduleRelation.getSourceType(); + String targetType = moduleRelation.getTargetType(); + // 1-1 1-N N-1 N-N 关系校验 + if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存一条记录 判断源实例是否有关系记录,同时判断目标实例是否已经有其他实例关系 + deal11PositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_1.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存全部记录 + deal1NPositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_1.equals(targetType)) { + // 保存一条记录 + dealN1PositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } else if (ModuleConstant.RELATION_TYPE_N.equals(sourceType) + && ModuleConstant.RELATION_TYPE_N.equals(targetType)) { + // 保存全部记录 + dealNNPositiveRelation(sourceInstance, targetRelationMap, moduleRelation, relationRule, userId); + } + } else { + log.info("没有满足规则的实例数据,删除表中已有实例关系"); + deletePositiveRelation(sourceInstance, moduleRelation, userId); + + } + log.info("结束处理实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向1-1关系 + * @CreateTime 2022/5/26 16:28 + */ + private void deal11PositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向1-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getTargetInstanceId()) + && !item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getTargetInstanceId)); + } + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + // 判断当前目标实例中是否有被占用的 + // 剩余满足条件且目标实例被使用的原实例关系 + if (relationIds.size() == 1 && CollectionUtils.isEmpty(oldConflictRelations)) { + Instance targetInstance = targetRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + // 不满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + if (CollectionUtils.isNotEmpty(relations)) { + conflictRelations.addAll(relations); + } + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelationMap.get(id))); + } + } + + if (relationIds.size() == 0 && oldKeepRelations.size() == 1) { + InstanceRelation relation = oldKeepRelations.get(0); + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + + log.info("结束处理正向1-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向1-N关系 + * @CreateTime 2022/5/26 16:28 + */ + private void deal1NPositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向1-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + // 冲突数据 + List oldConflictRelations = + oldRelations.stream().filter(item -> relationIds.contains(item.getTargetInstanceId()) + && !item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + Map> conflictRelationMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(oldConflictRelations)) { + conflictRelationMap = + oldConflictRelations.stream().collect(Collectors.groupingBy(InstanceRelation::getTargetInstanceId)); + } + // 实例关系 + List relationList = new ArrayList<>(); + for (Long id : relationIds) { + List conflicts = conflictRelationMap.get(id); + if (CollectionUtils.isEmpty(conflicts)) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetRelationMap.get(id), moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } else { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflicts)); + } + } + + //数据库中已有满足关联规则的关系,校验被关联方是否满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + List relations = conflictRelationMap.get(relation.getTargetInstanceId()); + //关联方不满足约束条件 + if (CollectionUtils.isNotEmpty(relations)) { + List conflictRelations = new ArrayList<>(); + conflictRelations.add(relation); + conflictRelations.addAll(relations); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, conflictRelations)); + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向1-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向N-1关系 + * @CreateTime 2022/5/26 16:28 + */ + private void dealN1PositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向N-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + if (CollectionUtils.isEmpty(oldKeepRelations)) { + if (relationIds.size() == 1) { + Instance targetInstance = targetRelationMap.get(relationIds.get(0)); + InstanceRelation relation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetInstance, moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId); + // 保存关系 + handler.saveInstanceRelation(relation, instanceRelationTable); + InstanceRelationHistoryRecord record = AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, + sourceInstance, targetInstance, moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), RelationHistoryConstant.Status.SUCCESS.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null); + list.add(record); + } else { + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + + } else { + if (relationIds.size() > 0 || oldKeepRelations.size() > 1) { + // 不满足约束条件 + for (InstanceRelation relation : oldKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(relation.getTargetInstanceId()), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, Arrays.asList(relation))); + } + for (Long id : relationIds) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, + RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.RECONCILED.getValue(), + RelationHistoryConstant.Type.RELATION.getValue(), userId, null)); + } + } + } + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(0, AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + + } + log.info("结束处理正向N-1关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * @param sourceInstance 源实例 + * @param targetRelationMap 满足规则的关系 + * @param moduleRelation 模型关系 + * @param userId + * @Description: 正向N-N关系 + * @CreateTime 2022/5/26 16:28 + */ + private void dealNNPositiveRelation(Instance sourceInstance, Map targetRelationMap, + ModuleRelation moduleRelation, AutoRelationRule relationRule, Long userId) throws Exception { + log.info("开始处理正向N-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + List relationIds = new ArrayList<>(targetRelationMap.keySet()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), null, moduleRelation.getTargetId(), null); + // 库中已有的关系 + List oldSourceRelations = oldRelations.stream() + .filter(item -> item.getSourceInstanceId().equals(sourceInstance.getId())).collect(Collectors.toList()); + // 库中已有满足条件的关系 + List oldKeepRelations = oldSourceRelations.stream() + .filter(item -> relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 库中已有不满足条件的关系 + List oldNoKeepRelations = oldSourceRelations.stream() + .filter(item -> !relationIds.contains(item.getTargetInstanceId())).collect(Collectors.toList()); + // 剩余满足条件的targetIds + relationIds.removeAll( + oldKeepRelations.stream().map(InstanceRelation::getTargetInstanceId).collect(Collectors.toList())); + // 执行历史 + List list = new ArrayList<>(); + // 实例关系 + List relationList = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldNoKeepRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + for (Long id : relationIds) { + relationList.add(AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, + targetRelationMap.get(id), moduleRelation, RelationHistoryConstant.Way.AUTO.getValue(), userId)); + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, + targetRelationMap.get(id), moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.RELATION.getValue(), + userId, null)); + } + if (CollectionUtils.isNotEmpty(relationList)) { + handler.batchSaveInstanceRelation(relationList, instanceRelationTable); + } + if (CollectionUtils.isNotEmpty(oldNoKeepRelarionIds)) { + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + } + if (CollectionUtils.isNotEmpty(list)) { + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向N-N关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + /** + * 构建实例数据 + * + * @param targetInstance + * @param moduleCode + * @throws Exception + */ + private void buildInstanceData(List targetInstance, String moduleCode) throws Exception { + for (Instance instance : targetInstance) { + // 查询实例数据 + List instanceValues = instanceValueRepository.listByInstanceId(instance.getId(), + CmdbUtils.CMDB_INSTANCE_VALUE + moduleCode.toLowerCase()); + instance.setInstanceValues(instanceValues); + } + } + + private void deletePositiveRelation(Instance sourceInstance, + ModuleRelation moduleRelation, Long userId) throws Exception { + log.info("开始处理正向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + // 关系表 + String instanceRelationTable = + CmdbUtils.CMDB_INSTANCE_RELATION + moduleRelation.getRelationCategoryCode().toLowerCase(); + // 查询该模型关系下的所有实例关系 + List oldRelations = instanceRelationRepository.queryByCondition(instanceRelationTable, + moduleRelation.getSourceId(), sourceInstance.getId(), moduleRelation.getTargetId(), null); + + if (CollectionUtils.isNotEmpty(oldRelations)) { + log.info("删除库中已有的实例关系,数量:{}", oldRelations.size()); + // 执行历史 + List list = new ArrayList<>(); + // 已有不满足条件的关系ids + List oldNoKeepRelarionIds = new ArrayList<>(); + for (InstanceRelation relation : oldRelations) { + list.add(AutoModuleInstanceRelationUtils.getInstanceRelationHistory(true, sourceInstance, null, + moduleRelation, relationRule, RelationHistoryConstant.Way.AUTO.getValue(), + RelationHistoryConstant.Status.SUCCESS.getValue(), RelationHistoryConstant.Type.CANCEL.getValue(), + userId, Arrays.asList(relation))); + oldNoKeepRelarionIds.add(relation.getId()); + } + // 删除已有不满足条件的 + instanceRelationRepository.removeByIds(oldNoKeepRelarionIds, instanceRelationTable, userId); + instanceRelationHistoryRecordRepository.batchSave(list, 100); + this.addOperationalAudit(list,userId); + } + log.info("结束处理正向没有满足条件的实例逻辑,删除库中已有的实例关系,实例id:{},模型code:{},模型关系id:{}", sourceInstance.getId(), sourceInstance.getModuleCode(), + moduleRelation.getId()); + } + + //操作审计 + private void addOperationalAudit(List list,Long userId) { + try { + List auditList = new ArrayList<>(); + for (InstanceRelationHistoryRecord historyRecord : list) { + if(!RelationHistoryConstant.Status.SUCCESS.getValue().equals(historyRecord.getStatus())){ + continue; + } + String props = historyRecord.getProps(); + //关联 + InstanceRelationHistoryAlterModel alter = null; + if (StringUtils.isNotEmpty(props)) { + alter = JSONObject.parseObject(historyRecord.getProps(), InstanceRelationHistoryAlterModel.class); + } + //关联 + Map afterMap = null; + Map beforeMap = null; + OperationalAudit audit = null; + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(historyRecord.getType())) { + + if (null != alter && CollectionUtils.isNotEmpty(alter.getBefore())) { + beforeMap = JSON.parseObject(JSON.toJSONString(alter.getBefore().get(0)), new TypeReference>() { + }); + } + audit = operationalAuditService.buildLog(OperationalAuditType.ASSOCIATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getId(), userId, beforeMap, afterMap); + + } else { + if (null != alter && null != alter.getAfter()) { + afterMap = + JSON.parseObject(JSON.toJSONString(alter.getAfter()), new TypeReference>() { + }); + } + + audit = operationalAuditService.buildLog(OperationalAuditType.RELATION, historyRecord.getModuleName(), + historyRecord.getName(), historyRecord.getModuleCode(), historyRecord.getId(), userId, beforeMap, afterMap); + } + + auditList.add(audit); + } + + if(!auditList.isEmpty()){ + operationalAuditRepository.batchSave(auditList, 100); + } + + }catch (Exception e){ + log.error("记录操作审计信息异常",e); + } + + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/AutoModuleInstanceRelationUtils.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/AutoModuleInstanceRelationUtils.java new file mode 100644 index 0000000..8ce351e --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/AutoModuleInstanceRelationUtils.java @@ -0,0 +1,410 @@ +package com.bocloud.ams.service.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.association.AutoRelationRule; +import com.bocloud.ams.entity.association.AutoRelationRuleItem; +import com.bocloud.ams.entity.association.AutoRelationRuleItemValue; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceRelationHistoryRecord; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.model.InstanceRelationHistoryAlterModel; +import com.bocloud.ams.entity.module.ModuleRelation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @Description: 判断两个实例是否有关系工具类 + * @Title: JudgeInstanceRelationUtils + * @Author: majiali + * @CreateTime: 2022/6/9 15:19 + */ +@Slf4j +public class AutoModuleInstanceRelationUtils { + + /** + * @param sourceInstance 当前实例信息(源) + * @param targetInstance 目标实例 + * @param relationRule 关联规则 + * @Description:判断两个实例是否有关系 正向判断 + * @Author majiali + * @CreateTime 2022/5/20 16:35 + */ + public static boolean isInstanceRelation(Instance sourceInstance, Instance targetInstance, AutoRelationRule relationRule) { + List instanceValues = sourceInstance.getInstanceValues(); + if (CollectionUtils.isEmpty(instanceValues)) { + return false; + } + Map sourceValueMap = instanceValues.stream().collect(Collectors.toMap(InstanceValue::getPropertyCode, Function.identity(), (oldData, newData) -> newData)); + List targetValues = targetInstance.getInstanceValues(); + if (CollectionUtils.isEmpty(targetValues)) { + return false; + } + Map targetValueMap = targetValues.stream().collect(Collectors.toMap(InstanceValue::getPropertyCode, Function.identity(), (oldData, newData) -> newData)); + //规则项 + List items = relationRule.getItems(); + boolean flag = true; + for (AutoRelationRuleItem item : items) { + if (!flag) { + break; + } + String sourceFieldCode = item.getSourceFieldCode(); + String sourceFieldType = item.getSourceFieldType(); + String targetFieldCode = item.getTargetFieldCode(); + String targetFieldType = item.getTargetFieldType(); + InstanceValue sourceValue = sourceValueMap.get(sourceFieldCode); + InstanceValue targetValue = targetValueMap.get(targetFieldCode); + if (null == sourceValue || StringUtils.isEmpty(sourceValue.getPropertyValue()) || null == targetValue || StringUtils.isEmpty(targetValue.getPropertyValue())) { + flag = false; + break; + } + //规则项value + List values = item.getValues(); + if (sourceFieldType.equals(PropertyConstant.PropertyType.SINGLELINETABLE) || sourceFieldType.equals(PropertyConstant.PropertyType.MULTILINETABLE) + || targetFieldType.equals(PropertyConstant.PropertyType.SINGLELINETABLE) || targetFieldType.equals(PropertyConstant.PropertyType.MULTILINETABLE)) { + if (CollectionUtils.isEmpty(values)) { + flag = false; + break; + } + } + //屬性行值 + String sourcePropertyValue = sourceValue.getPropertyValue(); + String targetPropertyValue = targetValue.getPropertyValue(); + //单行表格值为 JSONArray 类型 + //多行表格值为 JSONArray 类型 + switch (sourceFieldType) { + case PropertyConstant.PropertyType.SINGLELINETABLE: + case PropertyConstant.PropertyType.MULTILINETABLE: + switch (targetFieldType) { + case PropertyConstant.PropertyType.SINGLELINETABLE: + case PropertyConstant.PropertyType.MULTILINETABLE: + flag = multiTableCompareMultiTabel(sourcePropertyValue, targetPropertyValue, values); + break; + case PropertyConstant.PropertyType.MULTISELECT: + case PropertyConstant.PropertyType.CHECKBOX: + try { + JSONArray sourceArray = JSONArray.parseArray(sourcePropertyValue); + //目标为单个字段,规则字段只有一个 + AutoRelationRuleItemValue value = values.get(0); + flag = false; + for (Object a : sourceArray) { + JSONObject obj = (JSONObject) JSON.toJSON(a); + String sourcePropertyFieldValue = obj.getString(value.getSourceFieldCode()); + flag = compareCheckbox(sourcePropertyFieldValue, targetPropertyValue); + if (flag) { + break; + } + } + + } catch (Exception e) { + log.error("目标数据格式异常", targetPropertyValue); + flag = false; + } + break; + default: + try { + JSONArray sourceArray = JSONArray.parseArray(sourcePropertyValue); + //目标为单个字段,规则字段只有一个 + AutoRelationRuleItemValue value = values.get(0); + flag = false; + for (Object a : sourceArray) { + JSONObject obj = (JSONObject) JSON.toJSON(a); + String sourcePropertyFieldValue = obj.getString(value.getSourceFieldCode()); + if (StringUtils.isNotEmpty(sourcePropertyFieldValue) && sourcePropertyFieldValue.equals(targetPropertyValue)) { + flag = true; + break; + } + } + } catch (Exception e) { + log.error("目标数据格式异常", targetPropertyValue); + flag = false; + } + break; + } + break; + //源多选 + case PropertyConstant.PropertyType.MULTISELECT: + case PropertyConstant.PropertyType.CHECKBOX: + switch (targetFieldType) { + case PropertyConstant.PropertyType.SINGLELINETABLE: + case PropertyConstant.PropertyType.MULTILINETABLE: + try { + JSONArray targetArray = JSONArray.parseArray(targetPropertyValue); + //源为单个字段,规则字段只有一个 + AutoRelationRuleItemValue value = values.get(0); + flag = false; + for (Object a : targetArray) { + JSONObject obj = (JSONObject) JSON.toJSON(a); + String targetPropertyFieldValue = obj.getString(value.getTargetFieldCode()); + flag = compareCheckbox(sourcePropertyValue, targetPropertyFieldValue); + if (flag) { + break; + } + } + } catch (Exception e) { + log.error("目标数据格式异常", targetPropertyValue); + flag = false; + } + break; + default: + //直接比较是否有一个选择项相同 + flag = compareCheckbox(sourcePropertyValue, targetPropertyValue); + break; + } + break; + default: + switch (targetFieldType) { + case PropertyConstant.PropertyType.SINGLELINETABLE: + case PropertyConstant.PropertyType.MULTILINETABLE: + try { + JSONArray targetArray = JSONArray.parseArray(targetPropertyValue); + //源为单个字段,规则字段只有一个 + AutoRelationRuleItemValue value = values.get(0); + flag = false; + for (Object a : targetArray) { + JSONObject obj = (JSONObject) JSON.toJSON(a); + String targetPropertyFieldValue = obj.getString(value.getTargetFieldCode()); + if (StringUtils.isEmpty(targetPropertyFieldValue)) { + continue; + } + if (PropertyConstant.PropertyType.JSON.equals(sourceFieldType)) { + //判断json值是否一样 + flag = compareJson(sourcePropertyValue, targetPropertyValue); + if (flag) { + break; + } + } else { + if (sourcePropertyValue.equals(targetPropertyFieldValue)) { + flag = true; + break; + } + } + + } + + } catch (Exception e) { + log.error("目标数据格式异常", targetPropertyValue); + flag = false; + } + break; + default: + if (PropertyConstant.PropertyType.JSON.equals(sourceFieldType)) { + //判断json值是否一样 + flag = compareJson(sourcePropertyValue, targetPropertyValue); + } else { + if (!sourcePropertyValue.equals(targetPropertyValue)) { + flag = false; + } + } + break; + } + break; + } + } + return flag; + } + + /** + * 多行表格与多行表格比较 + */ + private static boolean multiTableCompareMultiTabel(String sourcePropertyValue, String targetPropertyValue, List values) { + boolean flag = true; + try { + JSONArray targetArray = JSONArray.parseArray(targetPropertyValue); + JSONArray sourceArray = JSONArray.parseArray(sourcePropertyValue); + for (AutoRelationRuleItemValue value : values) { + //一个规则的校验结果 + boolean singleResult = false; + for (Object a : sourceArray) { + JSONObject sourceObj = (JSONObject) JSON.toJSON(a); + String sourceValue = sourceObj.getString(value.getSourceFieldCode()); + for (Object b : targetArray) { + JSONObject targetObj = (JSONObject) JSON.toJSON(b); + String targetValue = targetObj.getString(value.getTargetFieldCode()); + if (PropertyConstant.PropertyType.CHECKBOX.equals(value.getSourceFieldType()) || PropertyConstant.PropertyType.MULTISELECT.equals(value.getSourceFieldType())) { + singleResult = compareCheckbox(sourceValue, targetValue); + if (singleResult) { + break; + } + } else { + //值比较 + if (StringUtils.isNotEmpty(sourceValue) && StringUtils.isNotEmpty(targetValue) && sourceValue.equals(targetValue)) { + singleResult = true; + break; + } + } + } + if (singleResult) { + break; + } + } + if (!singleResult) { + return false; + } + } + } catch (Exception e) { + flag = false; + } + return flag; + } + + /** + * json值比较 + */ + private static boolean compareJson(String sourcePropertyFieldValue, String targetPropertyFieldValue) { + try { + return JsonCompareUtil.campareJsonString(sourcePropertyFieldValue, targetPropertyFieldValue); + } catch (Exception e) { + log.error("json值比较异常", e); + return false; + } + } + + /** + * 多选字段值比较 + * ["position1","position2"] + */ + private static boolean compareCheckbox(String sourcePropertyFieldValue, String targetPropertyFieldValue) { + if (StringUtils.isEmpty(sourcePropertyFieldValue) || StringUtils.isEmpty(targetPropertyFieldValue)) { + return false; + } + List sourceValueList = JSONObject.parseArray(sourcePropertyFieldValue, String.class); + List targetValueList = JSONObject.parseArray(targetPropertyFieldValue, String.class); + for (String source : sourceValueList) { + if (targetValueList.contains(source)) { + return true; + } + } + return false; + } + + /** + * @param sourceInstance + * @param targetInstance + * @param moduleRelation + * @param way + * @param userId + * @Description: 获取实例关系 + * @Author majiali + * @CreateTime 2022/6/8 17:15 + */ + public static InstanceRelation getInstanceRelation(Instance sourceInstance, Instance targetInstance, ModuleRelation moduleRelation, String way, Long userId) { + InstanceRelation relation = new InstanceRelation(); + relation.setRelationCategoryId(moduleRelation.getRelationCategoryId()); + relation.setRelationCategoryCode(moduleRelation.getRelationCategoryCode()); + relation.setRelationId(moduleRelation.getRelationId()); + relation.setRelationName(moduleRelation.getRelationName()); + relation.setModuleRelationId(moduleRelation.getId()); + relation.setModuleRelationName(moduleRelation.getName()); + relation.setSourceModuleId(moduleRelation.getSourceId()); + relation.setSourceModuleCode(moduleRelation.getSourceCode()); + relation.setTargetModuleId(moduleRelation.getTargetId()); + relation.setTargetModuleCode(moduleRelation.getTargetCode()); + relation.setDeleted(false); + relation.setSourceInstanceId(sourceInstance.getId()); + relation.setSourceInstanceName(getInstanceName(sourceInstance)); + relation.setTargetInstanceId(targetInstance.getId()); + relation.setTargetInstanceName(getInstanceName(targetInstance)); + relation.setCreatorId(userId); + relation.setGmtCreate(new Date()); + relation.setSourceType(moduleRelation.getSourceType()); + relation.setTargetType(moduleRelation.getTargetType()); + relation.setWay(way); + return relation; + } + + /** + * @param isPositive 是否是正向关系 + * @param sourceInstance + * @param targetInstance + * @param moduleRelation + * @param way + * @param userId + * @Description: 获取调和记录 + * @Author majiali + * @CreateTime 2022/6/8 17:17 + */ + public static InstanceRelationHistoryRecord getInstanceRelationHistory(boolean isPositive, Instance sourceInstance, Instance targetInstance, ModuleRelation moduleRelation, AutoRelationRule relationRule, String way, String status, String type, Long userId, List oldConflictRelations) { + InstanceRelationHistoryRecord record = new InstanceRelationHistoryRecord(); + //当前实例是源实例 + if (isPositive) { + record.setName(getInstanceName(sourceInstance)); + record.setInstanceId(sourceInstance.getId()); + record.setModuleId(moduleRelation.getSourceId()); + record.setModuleCode(moduleRelation.getSourceCode()); + record.setModuleName(moduleRelation.getSourceName()); + if (null != targetInstance) { + record.setRelationInstanceId(targetInstance.getId()); + } + } else { + record.setName(getInstanceName(targetInstance)); + record.setInstanceId(targetInstance.getId()); + record.setModuleId(moduleRelation.getTargetId()); + record.setModuleCode(moduleRelation.getTargetCode()); + record.setModuleName(moduleRelation.getTargetName()); + if (null != sourceInstance) { + record.setRelationInstanceId(sourceInstance.getId()); + } + } + InstanceRelationHistoryAlterModel alter = new InstanceRelationHistoryAlterModel(); + //取消关联 + if (RelationHistoryConstant.Type.CANCEL.getValue().equals(type)) { + record.setAlterAfter("--"); + } else { + InstanceRelation instanceRelation = AutoModuleInstanceRelationUtils.getInstanceRelation(sourceInstance, targetInstance, moduleRelation, way, userId); + alter.setAfter(instanceRelation); + record.setAlterAfter(getInstanceName(sourceInstance) + "->" + getInstanceName(targetInstance)); + } + record.setRelationCategoryId(moduleRelation.getRelationCategoryId()); + record.setAutoRelationRuleId(relationRule.getId()); + record.setModuleRelationId(moduleRelation.getId()); + record.setIsSource(isPositive); + if (CollectionUtils.isEmpty(oldConflictRelations)) { + record.setAlterBefore("--"); + } else { + alter.setBefore(oldConflictRelations); + String beforeStr = ""; + for (InstanceRelation old : oldConflictRelations) { + beforeStr += old.getSourceInstanceName() + "->" + old.getTargetInstanceName() + ","; + } + if(StringUtils.isNotEmpty(beforeStr)){ + beforeStr = beforeStr.substring(0, beforeStr.length() - 1); + } + record.setAlterBefore(beforeStr); + } + record.setProps(JSONObject.toJSONString(alter)); + record.setDeleted(false); + record.setCreatorId(userId); + record.setGmtCreate(new Date()); + record.setWay(way); + record.setStatus(status); + record.setType(type); + if (!RelationHistoryConstant.Status.RECONCILED.getValue().equals(status)) { + record.setExecTime(new Date()); + record.setExecId(userId); + } + return record; + } + + private static String getInstanceName(Instance instance) { + String name = ""; + List instanceValues = instance.getInstanceValues(); + for (InstanceValue value : instanceValues) { + if ("name".equals(value.getPropertyCode())) { + name = value.getPropertyValue(); + break; + } + } + return name; + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/BoStringUtils.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/BoStringUtils.java new file mode 100644 index 0000000..ada08d9 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/BoStringUtils.java @@ -0,0 +1,336 @@ +package com.bocloud.ams.service.utils; + +import com.alibaba.fastjson.JSONObject; + +import java.sql.Date; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.util.List; +import java.util.regex.Pattern; + +/** + * 字符串处理类 + */ +public class BoStringUtils { + + /** + * 判断当前字符串中是否包含汉字 或全角字符 + * + * @param obj + * @return + */ + public static boolean hasChineseWord(Object obj) { + String s = BoStringUtils.toString(obj); + s = s.replaceAll("[^\\x00-\\xff]", "***"); + if (s.length() > BoStringUtils.toString(obj).length()) { + return true; + } + return false; + } + + public static long parseLong(String str) { + try { + + return Long.parseLong(str); + } catch (Exception ex) { + return 0L; + } + } + + public static int parseInt(String str) { + try { + + return Integer.parseInt(str); + } catch (Exception ex) { + return 0; + } + } + + public static int parseInt(String str, int i) { + try { + + return Integer.parseInt(str); + } catch (Exception ex) { + return i; + } + } + + public static double parseDouble(String str) { + try { + return Double.parseDouble(str); + } catch (Exception ex) { + return 0; + } + } + + public static String toString(Object obj) { + if (obj == null) { + return ""; + } + String className = obj.getClass().getName(); + if ("java.lang.String".equals(className)) { + return toString((String) obj).trim(); + } + if ("java.lang.Integer".equals(className)) { + return toString((Integer) obj).trim(); + } + if ("java.lang.Long".equals(className)) { + return toString((Long) obj).trim(); + } + if ("java.sql.Date".equals(className)) { + return toString((Date) obj).trim(); + } + if ("java.util.Date".equals(className)) { + return toString((java.util.Date) obj).trim(); + } + if ("java.lang.Float".equals(className)) { + return toString((Float) obj).trim(); + } + if ("java.sql.Timestamp".equals(className)) { + return toString((Timestamp) obj).trim(); + } + if ("java.lang.Double".equals(className)) { + return toString((Double) obj).trim(); + } + if ("com.alibaba.fastjson.JSONObject".equals(className)) { + return toString((JSONObject) obj).trim(); + } + + return obj.toString().trim(); + } + + /** + * 字符串 不启用trim + * + * @param obj + * @return + */ + public static String toStringAlias(Object obj) { + if (obj == null) { + return ""; + } + String className = obj.getClass().getName(); + if ("java.lang.String".equals(className)) { + return toString((String) obj); + } + if ("java.lang.Integer".equals(className)) { + return toString((Integer) obj).trim(); + } + if ("java.lang.Long".equals(className)) { + return toString((Long) obj).trim(); + } + if ("java.sql.Date".equals(className)) { + return toString((Date) obj).trim(); + } + if ("java.util.Date".equals(className)) { + return toString((java.util.Date) obj).trim(); + } + if ("java.lang.Float".equals(className)) { + return toString((Float) obj).trim(); + } + if ("java.sql.Timestamp".equals(className)) { + return toString((Timestamp) obj).trim(); + } + if ("java.lang.Double".equals(className)) { + return toString((Double) obj).trim(); + } + if ("com.alibaba.fastjson.JSONObject".equals(className)) { + return toString((JSONObject) obj).trim(); + } + + return obj.toString(); + } + + public static String toCSV(Object obj) { + String str = toString(obj); + return str.replaceAll("\"", "\"\"").replaceAll("\n", "").replaceAll("\r", ""); + } + + public static String toString(int obj) { + return String.valueOf(obj); + } + + public static String toString(long obj) { + return String.valueOf(obj); + } + + public static String toString(double obj) { + return String.valueOf(obj); + } + + public static String toString(float obj) { + return String.valueOf(obj); + } + + public static String toString(boolean obj) { + return String.valueOf(obj); + } + + public static String toString(char obj) { + return String.valueOf(obj); + } + + private static String toString(String obj) { + if (obj == null) { + return ""; + } + return obj; + } + + private static String toString(Integer obj) { + if (obj == null) { + return ""; + } + return obj.toString(); + } + + private static String toString(Long obj) { + if (obj == null) { + return ""; + } + return obj.toString(); + } + + private static String toString(Date obj) { + if (obj == null) { + return ""; + } + + DateFormat dftime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String str = dftime.format(obj); + if (str.indexOf("00:00:00") < 0) { + return str; + } else { + DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd"); + return df.format(obj); + } + } + + private static String toString(Double obj) { + if (obj == null) { + return ""; + } + return obj.doubleValue() + ""; + } + + private static String toString(Float obj) { + if (obj == null) { + return ""; + } + return obj.toString(); + } + + private static String toString(Timestamp obj) { + if (obj == null) { + return ""; + } + return obj.toString(); + } + + private static String toString(java.util.Date obj) { + if (obj == null) { + return ""; + } + return getDateString(obj); + } + + private static String getDateString(java.util.Date adate) { + + if (adate == null) { + return ""; + } + + DateFormat dftime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String str = dftime.format(adate); + if (str.indexOf("00:00:00") < 0) { + return str; + } else { + DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd"); + return df.format(adate); + } + + } + + public static boolean isEmpty(Object str) { + return "".equals(BoStringUtils.toString(str)); + } + + public static boolean isNotEmpty(Object str) { + return !"".equals(BoStringUtils.toString(str)); + } + + public static boolean isNumber(String str) { + if (str == null) { + return true; + } + String regExp = "^(-|\\+)?\\d+(\\.\\d+)?$"; + Pattern pattern = Pattern.compile(regExp); + return pattern.matcher(str).matches(); + } + + /** + * 判断是否只是数字、字母和下划线,过滤掉特殊字符 + * + * @param str + * @return + */ + public static boolean isNumberOrCharacter(String str) { + if (str == null) { + return false; + } + String regExp = "^[a-zA-Z0-9_]+$"; + Pattern pattern = Pattern.compile(regExp); + return pattern.matcher(str).matches(); + } + + /** + * 判断字符串是否包含字母 + * + * @param str + * @return + */ + public static boolean isIncludeLetter(String str) { + if (str == null) { + return false; + } + String regExp = "[a-zA-Z]+"; + Pattern pattern = Pattern.compile(regExp); + return pattern.matcher(str).find(); + } + + /*** + * 判断Key是否存在于数组中 + * @param keys + * @param key + * @return + */ + public static boolean isInclude(String[] keys, String key) { + for (String name : keys) { + if (name.equals(key)) { + return true; + } + } + return false; + } + + /** + * 将list按照一个分割符拼接到字符串后面 + * + * @param data + * @param list + * @param splite + * @return + */ + public static String appendString(String data, List list, String splite) { + StringBuffer sbBuffer = new StringBuffer(2048); + sbBuffer.append(data); + if (list != null) { + for (String str : list) { + if (BoStringUtils.isNotEmpty(str)) { + sbBuffer.append(str + splite); + } + } + } + return sbBuffer.toString(); + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/CollectionHistoryHelper.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/CollectionHistoryHelper.java new file mode 100644 index 0000000..83499f3 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/CollectionHistoryHelper.java @@ -0,0 +1,542 @@ +package com.bocloud.ams.service.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.collection.*; +import com.bocloud.ams.entity.enums.CollectionEnum; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.repository.collection.CollectionComponentRepository; +import com.bocloud.ams.repository.collection.CollectionTaskInstanceRepository; +import com.bocloud.ams.repository.collection.CollectionTaskRepository; +import com.bocloud.ams.repository.collection.CollectionTemplateRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.bocloud.ams.service.collection.CollectionHistoryService; +import com.bocloud.ams.service.instance.InstanceAutoRelationService; +import com.bocloud.ams.service.instance.InstanceService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.Common; +import com.megatron.common.utils.JSONTools; +import com.megatron.common.utils.ResultTools; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Slf4j +@Component("collectionHistoryHelper") +public class CollectionHistoryHelper { + @Autowired + private CollectionTaskInstanceRepository taskInstanceRepository; + @Autowired + private CollectionTaskRepository taskRepository; + @Autowired + private CollectionTemplateRepository templateRepository; + @Autowired + private CollectionComponentRepository componentRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private CollectionHistoryService historyService; + @Autowired + private InstanceService instanceService; + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private InstanceAutoRelationService instanceAutoRelationService; + + public GeneralResult history(Long taskInstanceId, String code, String output, Long operator) { + String userName = redisTemplate.opsForValue().get("User_Name_" + operator); + JSONObject object = JSONTools.isJSONObj(output); + if (null != object) { + try { + CollectionTaskInstance taskInstance = taskInstanceRepository.query(taskInstanceId); + if (null == taskInstance) { + return new GeneralResult(false, "采集任务实例不存在"); + } + CollectionTask task = taskRepository.query(taskInstance.getTaskId()); + if (null == task) { + return new GeneralResult(false, "采集任务不存在"); + } + CollectionTemplate template = templateRepository.query(task.getTemplateId()); + if (null == template) { + return new GeneralResult(false, "采集任务模板不存在"); + } + CiModule module = moduleRepository.query(task.getModuleId()); + if (null == module) { + return new GeneralResult<>(false, "模型不存在"); + } + //是否人工调和 + Boolean reconcile = task.getReconcile(); + //是否自动关联 + Boolean autoRelation = task.getAutoRelation(); + //查询模型属性 + List properties = propertyRepository.listNotHiddenByCmdbModuleId(task.getModuleId()); + Map propertyMap = new HashMap<>(); + for (Property property : properties) { + propertyMap.put(property.getCode(), property); + } + String instanceTable = CmdbUtils.CMDB_INSTANCE + module.getCode().toLowerCase(); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + module.getCode().toLowerCase(); + //查询所有实例 + List instanceValues = instanceValueRepository.listAll(instanceValueTable); + + Map> instanceMap = new HashMap(); + for (InstanceValue instanceValue : instanceValues) { + List instanceValueList = new ArrayList<>(); + if (instanceMap.containsKey(instanceValue.getInstanceId())) { + instanceValueList = instanceMap.get(instanceValue.getInstanceId()); + } + instanceValueList.add(instanceValue); + instanceMap.put(instanceValue.getInstanceId(), instanceValueList); + } + + //属性对照 + List components = componentRepository.queryByTemplateId(template.getId()); + Map componentMap = new HashMap(); + Map outMap = new HashMap(); + for (CollectionComponent component : components) { + if (CollectionEnum.parameter.CONTRAST.getValue().equals(component.getType())) { + componentMap.put(component.getName(), component); + } + if (CollectionEnum.parameter.OUTPUT.getValue().equals(component.getType())) { + componentMap.put(component.getName(), component); + outMap.put(component.getName(), component); + } + } + //输出参数为空,直接跳出 + if (outMap.isEmpty()) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.SUCCESS.name()); + return new GeneralResult(true, "保存成功"); + } + if (CollectionEnum.workerCode.DATABASE.getValue().equals(code)) { + dealDatabaseData(taskInstanceId, object, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + } else if (CollectionEnum.workerCode.SCRIPT.getValue().equals(code)) { + dealScriptData(taskInstanceId, object, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + } else if (CollectionEnum.workerCode.METHOD.getValue().equals(code)) { + dealMethodData(taskInstanceId, object, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + } + //剩下的实例属于未采集的 + for (Map.Entry> instance : instanceMap.entrySet()) { + CollectionHistory history = new CollectionHistory(); + history.setModuleId(module.getId()); + history.setInstanceId(instance.getKey()); + List instanceValuesList = instance.getValue(); + for (InstanceValue value : instanceValuesList) { + if (Common.UUID.equals(value.getPropertyCode())) { + history.setInstanceId(instance.getKey()); + } + } + history.setOperator(userName); + history.setGmtCreate(new Date()); + history.setTaskInstanceId(taskInstanceId); + history.setType(CollectionEnum.historyType.NOTCOLLECTED.name()); + history.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + historyService.create(history); + } + } catch (Exception e) { + log.error("采集记录保存失败:", e); + return new GeneralResult(true, "保存失败"); + } + return new GeneralResult(true, "保存成功"); + } else { + return ResultTools.formatErrResult(); + } + } + + private void dealDatabaseData(Long taskInstanceId, JSONObject object, Boolean reconcile, Map> instanceMap, Map componentMap, Map propertyMap, CiModule module, String userName, Long operator, Boolean autoRelation) throws Exception { + boolean updateRequiredInstance = true; + try { + JSONArray dataArray = object.getJSONArray("data"); + for (int i = 0; i < dataArray.size(); i++) { + List dataList = JSONArray.parseArray(String.valueOf(dataArray.get(i)), JSONObject.class); + dealData(taskInstanceId, dataList, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + updateRequiredInstance = false; + } + } catch (Exception e) { + log.error("处理数据库数据异常:", e); + } finally { + if (updateRequiredInstance) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.ERROR.name()); + } + } + + } + + /** + * 检测字符出现的数量 + * + * @param value + * @param sub + * @return + */ + public static int times(String value, String sub) { + int index; + int len = sub.length(); + int times = 0; + + while (value.indexOf(sub) != -1) { + index = value.indexOf(sub) + len; + value = value.substring(index); + times++; + } + return times; + } + + private void dealScriptData(Long taskInstanceId, JSONObject object, Boolean reconcile, Map> instanceMap, Map componentMap, Map propertyMap, CiModule module, String userName, Long operator, Boolean autoRelation) throws Exception { + boolean updateRequiredInstance = true; + try { + JSONArray dataArray = object.getJSONArray("data"); + List dataList = new ArrayList<>(); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObject = JSONObject.parseObject(JSON.toJSONString(dataArray.get(i))); + if (dataObject.getBooleanValue("success")) { + String stdout = JSONObject.parseObject(dataObject.getString("message")).getString("stdout"); + GeneralResult stdoutObj = JSONTools.isJSON(stdout); + if (stdoutObj.isSuccess()) { + dataList.add(stdoutObj.getData()); + } else { + String message = stdout.replaceAll("\\s*|\r|\n|\t", ""); + boolean existJson = message.contains("[") || message.contains("{"); + if (existJson) { + if(!message.endsWith(",")){ + message +=","; + } + JSONObject result = new JSONObject(); + //处理json的情况 + String jsonMessage = message; + String oneMessage = message; + int times = times(message, "["); + for (int j = 1; j <= times; j++) { + String key = StringUtils.substringAfterLast(StringUtils.substringBefore(jsonMessage, ":["), ","); + if (StringUtils.isEmpty(key)) { + continue; + } + String valueDate = StringUtils.substringBefore(StringUtils.substringAfter(jsonMessage, key + ":"), "],") + "]"; + String otherReplaceData = key + ":" + valueDate; + GeneralResult jsonValue = JSONTools.isJSONArray(valueDate); + if (jsonValue.isSuccess()) { + JSONArray value = JSONArray.parseArray(valueDate); + result.put(key, value); + jsonMessage = StringUtils.substringAfter(jsonMessage, otherReplaceData); + oneMessage = oneMessage.replace(otherReplaceData, "").replaceAll(",,", ","); + }else { + if (valueDate.startsWith("[") && valueDate.endsWith("]")) { + try { + result.put(key, JSONArray.parseArray(valueDate)); + jsonMessage = StringUtils.substringAfter(jsonMessage, otherReplaceData); + oneMessage = oneMessage.replace(otherReplaceData, "").replaceAll(",,", ","); + } catch (Exception e) { + //字符串转数组出错,考虑是字符串中包含]、}]等问题引起的,需要特殊处理下 + //兼容字符串中包含]、}]字符 + // 包含"}]的还没有兼容,解析的时候还是会有问题 + valueDate = StringUtils.substringBefore(StringUtils.substringAfter(jsonMessage, key + ":"), "}],") + "}]"; + otherReplaceData = key + ":" + valueDate; + jsonValue = JSONTools.isJSONArray(valueDate); + if (jsonValue.isSuccess()) { + result.put(key, jsonValue.getData()); + jsonMessage = StringUtils.substringAfter(jsonMessage, otherReplaceData); + oneMessage = oneMessage.replace(otherReplaceData, "").replaceAll(",,", ","); + } else { + valueDate = StringUtils.substringBefore(StringUtils.substringAfter(jsonMessage, key + ":"), "\"}],") + "\"}]"; + otherReplaceData = key + ":" + valueDate; + jsonValue = JSONTools.isJSONArray(valueDate); + if (jsonValue.isSuccess()) { + result.put(key, jsonValue.getData()); + jsonMessage = StringUtils.substringAfter(jsonMessage, otherReplaceData); + oneMessage = oneMessage.replace(otherReplaceData, "").replaceAll(",,", ","); + } + } + } + + } + } + + } + + jsonMessage = oneMessage; + int timesObj = times(oneMessage, "{"); + for (int j = 1; j <= timesObj; j++) { + String key = StringUtils.substringAfterLast(StringUtils.substringBefore(jsonMessage, ":{"), ","); + if (StringUtils.isEmpty(key)) { + continue; + } + String valueDate = StringUtils.substringBefore(StringUtils.substringAfter(jsonMessage, key + ":"), "}") + "}"; + String otherReplaceData = key + ":" + valueDate; + GeneralResult jsonValue = JSONTools.isJSON(valueDate); + if (jsonValue.isSuccess()) { + JSONObject value = JSONObject.parseObject(valueDate); + result.put(key, value); + jsonMessage = StringUtils.substringAfter(jsonMessage, otherReplaceData); + oneMessage = oneMessage.replace(otherReplaceData, "").replaceAll(",,", ","); + } + + } + + //处理1对1的情况 + String[] oneDataSplit = oneMessage.split(","); + for (String msg : oneDataSplit) { + if (msg.contains(":")) { + String[] msgSplit = msg.split(":"); + result.put(msgSplit[0], msg.substring(msgSplit[0].length() + 1)); + } + } + dataList.add(result); + } else { + String[] messageSplit = message.split(","); + JSONObject data = new JSONObject(); + for (String msg : messageSplit) { + if (msg.contains(":")) { + String[] msgSplit = msg.split(":"); + data.put(msgSplit[0], msg.substring(msgSplit[0].length() + 1)); + } + } + dataList.add(data); + } + } + updateRequiredInstance = false; + } + } + dealData(taskInstanceId, dataList, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + } catch (Exception e) { + log.error("处理脚本数据异常:", e); + } finally { + if (updateRequiredInstance) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.ERROR.name()); + } + } + } + + private void dealMethodData(Long taskInstanceId, JSONObject object, Boolean reconcile, Map> instanceMap, Map componentMap, Map propertyMap, CiModule module, String userName, Long operator, Boolean autoRelation) throws Exception { + boolean updateRequiredInstance = true; + try { + JSONObject dataObject = object.getJSONObject("data"); + if (dataObject.getBooleanValue("success")) { + List dataList = new ArrayList<>(); + GeneralResult result = JSONTools.isJSON(dataObject.getString("data")); + if (result.isSuccess()) { + JSONObject dataObj = dataObject.getJSONObject("data"); + dataList.add(dataObj); + } else { + dataList = JSONArray.parseArray(dataObject.getString("data"), JSONObject.class); + } + dealData(taskInstanceId, dataList, reconcile, instanceMap, componentMap, propertyMap, module, userName, operator, autoRelation); + updateRequiredInstance = false; + } + } catch (Exception e) { + log.error("处理接口数据异常:", e); + } finally { + if (updateRequiredInstance) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.ERROR.name()); + } + } + } + + private void dealData(Long taskInstanceId, List dataList, Boolean reconcile, Map> instanceMap, Map componentMap, Map propertyMap, CiModule module, String userName, Long operator, Boolean autoRelation) { + try { + int successCount = 0; + int failCount = 0; + for (JSONObject data : dataList) { + //转换成:属性:数据 + Map dataMap = new HashMap<>(); + Map contrastDataMap = new HashMap<>(); + Map outputDataMap = new HashMap<>(); + for (Map.Entry entry : data.entrySet()) { + if (componentMap.containsKey(entry.getKey())) { + CollectionComponent component = componentMap.get(entry.getKey()); + if (CollectionEnum.parameter.CONTRAST.getValue().equals(component.getType())) { + contrastDataMap.put(component.getPropertyCode(), entry.getValue()); + } else if (CollectionEnum.parameter.OUTPUT.getValue().equals(component.getType())) { + outputDataMap.put(component.getPropertyCode(), entry.getValue()); + } + dataMap.put(component.getPropertyCode(), entry.getValue()); + } + } + Map oldDataMap = new HashMap<>(); + //匹配实例数据 + Long instanceId = null; + String instanceUuId = null; + //存放当前实例属性值 + Map valueMap = new HashMap<>(); + for (Map.Entry> instance : instanceMap.entrySet()) { + boolean isCurrent = true; + List instanceValues = instance.getValue(); + valueMap = new HashMap<>(); + for (InstanceValue value : instanceValues) { + valueMap.put(value.getPropertyCode(), value.getPropertyValue()); + } + for (Map.Entry entry : contrastDataMap.entrySet()) { + if (!valueMap.containsKey(entry.getKey()) || (null != valueMap.get(entry.getKey()) && !valueMap.get(entry.getKey()).equals(contrastDataMap.get(entry.getKey())))) { + isCurrent = false; + break; + } + } + if (isCurrent) { + instanceId = instance.getKey(); + //取出原属性值 + oldDataMap = new HashMap<>(); + List oldValues = instanceMap.get(instanceId); + for (InstanceValue value : oldValues) { + if (Common.UUID.equals(value.getPropertyCode())) { + instanceUuId = value.getPropertyValue(); + } + if (dataMap.containsKey(value.getPropertyCode())) { + oldDataMap.put(value.getPropertyCode(), value.getPropertyValue()); + //剔除替换的 + valueMap.remove(value.getPropertyCode()); + } + } + instanceMap.remove(instanceId); + break; + } + } + //封装实例数据 + JSONObject instanceObject = new JSONObject(); + instanceObject.put("moduleId", module.getId()); + instanceObject.put("moduleCode", module.getCode()); + + CollectionHistory history = new CollectionHistory(); + history.setModuleId(module.getId()); + history.setOperator(userName); + history.setGmtCreate(new Date()); + history.setTaskInstanceId(taskInstanceId); + history.setOutput(JSON.toJSONString(data)); + if (null != instanceId && !oldDataMap.isEmpty()) { + history.setInstanceId(instanceId); + history.setInstanceUuid(instanceUuId); + history.setType(CollectionEnum.historyType.EDIT.name()); + instanceObject.put(Common.ID, instanceId); + instanceObject.put(Common.UUID, instanceUuId); + } else { + history.setType(CollectionEnum.historyType.ADD.name()); + } + boolean isNeedUpdate = false; + List items = new ArrayList<>(); + for (Map.Entry entry : dataMap.entrySet()) { + if (propertyMap.containsKey(entry.getKey())) { + Property property = propertyMap.get(entry.getKey()); + CollectionHistoryItem item = new CollectionHistoryItem(); + item.setPropertyId(property.getId()); + item.setPropertyCode(property.getCode()); + if (CollectionEnum.historyType.EDIT.name().equals(history.getType()) && null != oldDataMap.get(property.getCode())) { + item.setBeforeValue(String.valueOf(oldDataMap.get(property.getCode()))); + } else if (CollectionEnum.historyType.ADD.name().equals(history.getType())) { + isNeedUpdate = true; + } + if (null != entry.getValue()) { + item.setAfterValue(String.valueOf(entry.getValue())); + } + if ((null != oldDataMap.get(property.getCode()) && null != entry.getValue() && !oldDataMap.get(property.getCode()).equals(entry.getValue())) || (null == oldDataMap.get(property.getCode()) && null != entry.getValue()) || (null != oldDataMap.get(property.getCode()) && null == entry.getValue())) { + isNeedUpdate = true; + } + items.add(item); + + // instanceObject.put(property.getCode(), entry.getValue()); + if ((PropertyConstant.PropertyType.CHECKBOX.equals(property.getType()) || PropertyConstant.PropertyType.MULTISELECT.equals(property.getType()) || PropertyConstant.PropertyType.JSON.equals(property.getType()) || PropertyConstant.PropertyType.SINGLELINETABLE.equals(property.getType()) || PropertyConstant.PropertyType.MULTILINETABLE.equals(property.getType())) && null != entry.getValue() && StringUtils.isNotEmpty(String.valueOf(entry.getValue()))) { + GeneralResult result = JSONTools.isJSON(String.valueOf(entry.getValue())); + if (result.isSuccess()) { + instanceObject.put(property.getCode(), JSONObject.parseObject(String.valueOf(entry.getValue()))); + } else { + instanceObject.put(property.getCode(), JSONArray.parseArray(String.valueOf(entry.getValue()))); + } + } else { + instanceObject.put(property.getCode(), entry.getValue()); + } + } + } + if (!isNeedUpdate) { + history.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + history.setType(CollectionEnum.historyType.NOUPDATE.name()); + successCount += 1; + } + history.setHistoryItems(items); + + if (null != reconcile && !reconcile && isNeedUpdate) { + if (null != instanceId && !oldDataMap.isEmpty()) { + //未采集的属性值保留 + for (Map.Entry entry : valueMap.entrySet()) { + if (propertyMap.containsKey(entry.getKey())) { + instanceObject.put(entry.getKey(), entry.getValue()); + } + } + GeneralResult result = instanceService.modify(instanceObject, operator); + if (result.isSuccess()) { + history.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + successCount += 1; + //自动关联 + if (autoRelation) { + log.info("开启实例自动关联关系;"); + try { + Instance instance = (Instance) result.getData(); + instanceAutoRelationService.instanceAutoRelation(instance, operator); + } catch (Exception e) { + log.error("采集任务中存在实例关系自动关联失败情况", e); + } + } + } else { + history.setStatus(CollectionEnum.historyStatus.FAILED.name()); + history.setReason(result.getMessage()); + failCount += 1; + } + } else { + //如果名称为空则自动生产 + if (null == instanceObject.getString("name")) { + instanceObject.put("name", "AutomaticGeneration" + System.currentTimeMillis()); + } + GeneralResult result = instanceService.create(instanceObject, operator, false); + if (result.isSuccess()) { + Instance instance = (Instance) result.getData(); + history.setInstanceId(instance.getId()); + history.setInstanceUuid(instance.getUuid()); + history.setStatus(CollectionEnum.historyStatus.SUCCESS.name()); + successCount += 1; + //自动关联 + if (autoRelation) { + log.info("开启实例自动关联关系;"); + try { + instanceAutoRelationService.instanceAutoRelation(instance, operator); + } catch (Exception e) { + log.error("采集任务中存在实例关系自动关联失败情况", e); + } + } + } else { + history.setStatus(CollectionEnum.historyStatus.FAILED.name()); + history.setReason(result.getMessage()); + failCount += 1; + } + } + } else if ((null == reconcile || reconcile) && isNeedUpdate) { + history.setStatus(CollectionEnum.historyStatus.RECONCILED.name()); + } + historyService.create(history); + } + //最后更新任务状态 + if (dataList.size() == successCount) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.SUCCESS.name()); + } else if (0 != failCount) { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.ERROR.name()); + } + } catch (Exception e) { + log.error("处理数据异常:", e); + try { + taskInstanceRepository.updateStatus(taskInstanceId, CollectionEnum.Status.ERROR.name()); + }catch (Exception e1){ + log.error("更新实例状态异常:", e1); + } + + } + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/EventPublisher.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/EventPublisher.java new file mode 100644 index 0000000..9fefb43 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/EventPublisher.java @@ -0,0 +1,42 @@ +package com.bocloud.ams.service.utils; + + +import com.bocloud.cmp.boot.model.BoCloudExchange; +import com.megatron.common.model.OperateResult; +import com.megatron.common.model.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.AmqpException; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @ClassName: EventPublisher + * @Description 事件通知 + * @Author yangzhenrong + * @Date 2022/6/10 11:05 + * @Version 1.0 + **/ +@Slf4j +@Component +public class EventPublisher { + @Autowired + private AmqpTemplate amqpTemplate; + private static String EXCHANGE = BoCloudExchange.Default.TOPIC.getExchange(); + private static String ROUITING = "bocloud.message.queue.#"; + + public Result send(Object message) { + try { + if (message instanceof OperateResult) { + OperateResult result = (OperateResult) message; + result.setOperate(null == result.getOperate() ? "" : result.getOperate()); + message = result; + } + this.amqpTemplate.convertAndSend(EXCHANGE, ROUITING, message); + return new Result(true, "success"); + } catch (AmqpException e) { + log.error("Send Event Error:", e); + return new Result(false, "发送失败"); + } + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelFactory.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelFactory.java new file mode 100644 index 0000000..ef35c28 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelFactory.java @@ -0,0 +1,210 @@ +package com.bocloud.ams.service.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.*; + +/** + * @ClassName: ExcelFactory + * @Description excel构造工厂 + * @Author yangzhenrong + * @Date 2022/5/25 14:19 + * @Version 1.0 + **/ +@Slf4j +public class ExcelFactory { + public enum ExcelType { + /** + * 老版本 office + */ + EXCEL2000, + /** + * 新版本office + */ + EXCEL2007 + } + + // excel类型 + protected ExcelType excelType = null; + private InputStream fis = null; + + public ExcelType getExcelType() { + return excelType; + } + + public void setExcelType(ExcelType excelType) { + this.excelType = excelType; + } + + /** + * 创建文本单元格 + * + * @param args + * @return + */ + public RichTextString newRichTextString(String args) { + switch (excelType) { + case EXCEL2000: + return new HSSFRichTextString(args); + case EXCEL2007: + return new XSSFRichTextString(args); + default: + return new HSSFRichTextString(args); + } + } + + public ExcelFactory(File file, String fileName) { + try { + if (fileName == null || "".equals(fileName)) { + if (file.getName().endsWith(".xls")) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + } else { + if (fileName.endsWith(".xls")) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + } + + fis = new FileInputStream(file); + } catch (FileNotFoundException e) { + log.error("文件处理失败", e); + } + } + + public ExcelFactory(InputStream fis, String fileName) { + try { + + if (fileName.endsWith(".xls")) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + this.fis = fis; + } catch (Exception e) { + log.error("文件处理失败", e); + } + + } + + public ExcelFactory(Row row) { + if (row instanceof HSSFRow) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + } + + public ExcelFactory(Workbook wb) { + if (wb instanceof HSSFWorkbook) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + + } + + public ExcelFactory(Sheet sheet) { + if (sheet instanceof HSSFSheet) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + } + + public ExcelFactory() { + excelType = ExcelType.EXCEL2000; + + } + + public ExcelFactory(String fileName) { + if (fileName.endsWith(".xls")) { + excelType = ExcelType.EXCEL2000; + } else { + excelType = ExcelType.EXCEL2007; + } + } + + public void closeQuietly() { + IOUtils.closeQuietly(fis); + } + + public Workbook newWorkbook() { + switch (excelType) { + case EXCEL2000: + if (fis == null) { + return new HSSFWorkbook(); + } else { + try { + return new HSSFWorkbook(fis); + } catch (IOException e) { + log.error("文件处理失败", e); + } + } + + case EXCEL2007: + if (fis == null) { + return new XSSFWorkbook(); + } else { + try { + return new XSSFWorkbook(fis); + } catch (IOException e) { + log.error("文件处理失败", e); + } + } + default: + return new HSSFWorkbook(); + } + + } + + public DataValidation newDataValidation(CellRangeAddressList cellRangeAddressList, String[] textlist, Sheet sheet, + String formula) { + DataValidation validation = null; + switch (excelType) { + case EXCEL2000: + validation = new HSSFDataValidation(cellRangeAddressList, getExcel2000DataValidation(textlist, formula)); + return validation; + case EXCEL2007: + XSSFDataValidationHelper helper = new XSSFDataValidationHelper((XSSFSheet) sheet); + validation = helper.createValidation(getExcel2007DataValidation(helper, textlist, formula), + cellRangeAddressList); + return validation; + default: + return validation; + } + + } + + public static DVConstraint getExcel2000DataValidation(String[] textlist, String formula) { + DVConstraint constraint = null; + if (formula == null) { + constraint = DVConstraint.createExplicitListConstraint(textlist); + } else { + constraint = DVConstraint.createFormulaListConstraint(formula); + } + return constraint; + } + + public static DataValidationConstraint getExcel2007DataValidation(XSSFDataValidationHelper helper, + String[] textlist, String formula) { + DataValidationConstraint constraint = null; + if (formula == null) { + constraint = helper.createExplicitListConstraint(textlist); + } else { + constraint = helper.createFormulaListConstraint(formula); + } + return constraint; + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelHelper.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelHelper.java new file mode 100644 index 0000000..d986ef9 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ExcelHelper.java @@ -0,0 +1,605 @@ +package com.bocloud.ams.service.utils; + +import com.megatron.common.utils.ListTool; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.xssf.usermodel.XSSFSheet; + +import java.text.DecimalFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Excel工具类 + * + * @author liuyuanyuan + */ +@Slf4j +public class ExcelHelper { + public enum EnumHelper { + /** + * 老版office + */ + EXCEL2000("2000"), + /** + * 新版office + */ + EXCEL2007("2007"), + /** + * excel列数最大值 + */ + ExcelColumnMax("255"), + /** + * 计算行数时,从上数还是从下数的判断值 + */ + ExcelRowBoundary("100"), + /** + * 判断当前行是否有数据,判断前多少列,而不是判断满255 + */ + ExcelCellBoundary("20"), + /** + * excel单元格值 若为科学计数法的 开始是E + */ + ExcelCellDoubleValueprefix("E"), + /** + * excel单元格值 是数字格式的特征 + */ + ExcelCellfloatValueprefix(".0"), + /** + * excel单元格值 取值时 + */ + ExcelCellfloatPatten("#.############"), + /** + * 附表值sheet页名称 + */ + Schedulevalue("Schedulevalue"); + + String value; + + EnumHelper(String running) { + this.value = running; + } + + public String getValue() { + return value; + } + + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @param newSheetFlag 长度超过255,生成附表值sheet页以及数据 + * @return 设置好的sheet. + */ + public static Sheet setValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, + int endCol, Boolean newSheetFlag) { + String formula = null; + if (newSheetFlag) { + int cellnum = generateSchedulevalueSheet(sheet, textlist); + String character = generateColumnName(cellnum); + formula = EnumHelper.Schedulevalue.getValue() + "!$" + character + "$" + 1 + ":$" + character + "$" + + textlist.length; + } + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidationList = new ExcelFactory(sheet).newDataValidation(regions, textlist, sheet, + formula); + // 输入错误时,警告 + if (dataValidationList != null) { + dataValidationList.setShowErrorBox(true); + sheet.addValidationData(dataValidationList); + } + return sheet; + } + + /** + * 多excel列进行处理,获得列名 + * + * @param index 索引 + * @return 列名 + */ + private static String generateColumnName(int index) { + String result = ""; + int myindex = index; + int times = myindex / 26; + int remainder = myindex % 26; + result += times == 0 ? "" : times == 1 ? "A" : "B"; + result += (char) (remainder + 65); + return result; + } + + /** + * 生成附表值sheet页以及相应的附表值 + * + * @param sheet + * @param textlist + */ + private static int generateSchedulevalueSheet(Sheet sheet, String[] textlist) { + Workbook wb = sheet.getWorkbook(); + Sheet sheetSchedulevalue = wb.getSheet(EnumHelper.Schedulevalue.getValue()); + if (sheetSchedulevalue == null) { + sheetSchedulevalue = wb.createSheet(EnumHelper.Schedulevalue.getValue()); + int sheetIx = wb.getSheetIndex(EnumHelper.Schedulevalue.getValue()); + wb.setSheetHidden(sheetIx, true); + } + // 寻在空白列 + Row row1 = sheetSchedulevalue.getRow(0); + int cellnum = 0; + while (row1 != null && row1.getCell(cellnum) != null) { + cellnum++; + } + Row row = null; + for (int i = 0; i < textlist.length; i++) { + row = sheetSchedulevalue.getRow(i); + if (row == null) { + // 第一行 + row = sheetSchedulevalue.createRow(i); + } + + Cell cell = row.createCell(cellnum); + cell.setCellValue(new ExcelFactory(row).newRichTextString(textlist[i])); + } + return cellnum; + } + + /** + * 合并分组信息 + * + * @param sheet + * @param cellStyle + */ + public static void generateMergedRegion(Sheet sheet, CellStyle cellStyle) { + Row row0 = sheet.getRow(0); + + // 合并单元格的开始列 + int start = 0; + // 合并的结束列 + int end = 0; + // 合并单元格内的内容 + String value = ""; + for (int i = row0.getFirstCellNum(); i < ExcelHelper.getLastCellNum(row0); i++) { + Cell cell = row0.getCell(i); + // 合并单元格内赋值用 + Cell cellBefore; + String cellValue = BoStringUtils.toString(ExcelHelper.getCellValue(cell)); + // 当前单元格 和前面的不一样,说明前面的可以合并了 + if (!cellValue.equals(value) || i == ExcelHelper.getLastCellNum(row0) - 1) { + // 如果遍历到了最后,要特殊考虑下,能合并就合并 + if (i == ExcelHelper.getLastCellNum(row0) - 1 && cellValue.equals(value)) { + end = i; + } + // 超过1个才合并 不然没必要 + if (end - start > 1) { + CellRangeAddress cra = new CellRangeAddress(0, 0, start, end); + sheet.addMergedRegion(cra); + cellBefore = row0.createCell(start); + cellBefore.setCellValue(new ExcelFactory(row0).newRichTextString(value)); + cellBefore.setCellStyle(cellStyle); + } + start = i; + value = cellValue; + } else { + end = i; + } + } + + } + + ; + + /** + * 获取行 内容不为空的最后一列 + * + * @param row + * @return + */ + private static int getLastCellNum(Row row) { + // 最后一个有效单元格的位置 + short lastNum = 0; + if (row.getLastCellNum() < BoStringUtils.parseInt(EnumHelper.ExcelColumnMax.getValue())) { + return row.getLastCellNum(); + } + for (int i = 0; i < BoStringUtils.parseInt(EnumHelper.ExcelColumnMax.getValue()); i++) { + // 如果当前单元格不是null 并且有值 + if (!"".equals(ExcelHelper.getCellValue(row.getCell(i)))) { + lastNum = (short) i; + } + } + return lastNum; + } + + /** + * 数据导入时进行类型转换 + * + * @param cell excel单元格对象 + * @return string 经过处理后的字符串对象 + * @throws Exception + */ + public static String getCellValue(Cell cell) { + if (cell == null) { + return ""; + } + if (CellType.STRING == cell.getCellTypeEnum()) { + // 字符串格式(默认) + return BoStringUtils.toString(cell.getRichStringCellValue()); + } else if (CellType.BOOLEAN == cell.getCellTypeEnum()) { + // 布尔 + return BoStringUtils.toString(cell.getBooleanCellValue()); + } else if (CellType.NUMERIC == cell.getCellTypeEnum()) { + // 数字格式 + // 解决POI导入Excel日期识别成数字的方法 + if (DateUtil.isCellDateFormatted(cell)) { + double d = cell.getNumericCellValue(); + Date date = DateUtil.getJavaDate(d); + return BoStringUtils.toString(date); + } + String str = BoStringUtils.toString(cell.getNumericCellValue()); + // 转换double科学计数法,为字符串 || 单元格整数 去掉小数点'.0' + if (str.indexOf(EnumHelper.ExcelCellDoubleValueprefix.getValue()) > 0 + || str.indexOf(EnumHelper.ExcelCellfloatValueprefix.getValue()) > 0) { + DecimalFormat decimalFormat = new DecimalFormat(EnumHelper.ExcelCellfloatPatten.getValue()); + // 一个数字,不包括 0 + str = decimalFormat.format(Double.parseDouble(str)); + } + return str; + } else if (CellType.FORMULA == cell.getCellTypeEnum()) { + // 公式 + return BoStringUtils.toString(cell.getCellFormula()); + } else if (CellType.ERROR == cell.getCellTypeEnum()) { + return "错误单元格,数据获取失败。"; + // throw new Exception("第" + (Integer.toString(cell.getRowIndex() + + // 1) + "行第" + // + Integer.toString(cell.getColumnIndex() + 1) + + // "列单元格有错误,请核实原始模板!")); + } else { + return BoStringUtils.toString(cell.getStringCellValue()); + } + } + + /** + * 设置文本格式以及调整列宽,使之能完整显示字段名称 + * + * @param wb 工作薄对象 + */ + public static void setTextformatAndColumnwidth(Workbook wb) { + // 设置文本格式 + DataFormat format = wb.createDataFormat(); + CellStyle style = wb.createCellStyle(); + style.setDataFormat(format.getFormat("@")); + for (int m = 0; m < wb.getNumberOfSheets(); m++) { + // 获取第m个Sheet + Sheet sheet = wb.getSheetAt(m); + // 获取第2行 名称 + Row row1 = sheet.getRow(1); + // 获取第3行 编码 + Row row2 = sheet.getRow(2); + + if (row1 == null || row2 == null) { + continue; + } + for (int i = 0; i < ExcelHelper.getLastCellNum(row1); i++) { + Cell cell1 = row1.getCell(i); + Cell cell2 = row2.getCell(i); + + String s1 = "", s2 = "", s = ""; + // 2、3行谁的长度大,取谁的列宽 + if (cell1 != null) { + s1 = BoStringUtils.toString(cell1.getRichStringCellValue()); + } + if (cell2 != null) { + s2 = BoStringUtils.toString(cell2.getRichStringCellValue()); + } + if ("".equals(s1) && "".equals(s2)) { + continue; + } + if (s1.getBytes().length > s2.getBytes().length) { + s = s1; + } else { + s = s2; + } + int width = s.getBytes().length * 256; + width = width > 10000 ? 10000 : width; + if (sheet.getColumnWidth(i) < width) { + // 汉字是512,数字是256. + sheet.setColumnWidth(i, width); + // 设置文本格式 + sheet.setDefaultColumnStyle((short) i, style); + } + } + + } + } + + /** + * 行错误信息放置 + * + * @param row + * @param message + */ + public static void promptErrorMessage(Row row, String message) { + Cell cell = row.createCell(0); + if (!message.contains("成功")) { + CellStyle cellStyle = row.getSheet().getWorkbook().createCellStyle(); + Font font = row.getSheet().getWorkbook().createFont(); + font.setColor(Font.COLOR_RED); + cellStyle.setFont(font); + cell.setCellStyle(cellStyle); + } + cell.setCellValue(new ExcelFactory(row).newRichTextString(message)); + } + + /** + * 获取sheet名字中的模型编码 + * + * @param sheetName + * @return + */ + public static String regexSheetModuleCode(String sheetName) { + String regex = ".*?\\((.*?)\\).*?"; + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(sheetName); + if (matcher.find()) { + return matcher.group(1); + } + return ""; + } + + /** + * sheet 全局报错信息放置 + * + * @param wb + * @param message + */ + public static void promptErrorMessage(Workbook wb, String message) { + Sheet sheet = wb.getSheetAt(0); + wb.setActiveSheet(0); + wb.setSelectedTab(0); + Row row = sheet.getRow(0); + if (row == null) { + row = sheet.createRow(0); + } + // 设置错误提示字体红色、加粗 + Cell cell = row.createCell(0); + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + font.setColor(Font.COLOR_RED); + cellStyle.setFont(font); + // 设置表头样式 + cell.setCellStyle(cellStyle); + cell.setCellValue(new ExcelFactory(row).newRichTextString(message)); + } + + /** + * 读取表头 + * + * @param row excel行对象 + * @return header map集合对象 + */ + public static Map readHeader4NameKey(Row row, Integer start) { + if (row == null) { + throw new RuntimeException("1、请检查是否是最新版本;\n" + "2、不要更改模板格式;\n" + "3、请重新下载模板;"); + } + Map header = new HashMap(30); + try { + for (int i = start; i < ExcelHelper.getLastCellNum(row); i++) { + Cell cell = row.getCell(i); + // 有错误信息栏目 + if (cell != null && !"".equals(ExcelHelper.getCellValue(cell))) { + String value = ExcelHelper.getCellValue(cell); + header.put(value, new Integer(i)); + } + } + } catch (Exception e) { + log.error("检查表头报错", e); + throw new RuntimeException("1、请检查是否是最新版本;\n" + "2、不要更改模板格式;\n" + "3、请重新下载模板;\n"); + } + + return header; + } + + /** + * 调用此方法(从第三行算第一条数据) + * + * @param sheet + * @return + */ + public static int getRowNumberOfSheet(Sheet sheet) { + return getRowNumberOfSheet(sheet, 0); + } + + /** + * 获得sheet页行数,空白行删掉 + * + * @param sheet + * @param rowNumber + * @return + */ + private static int getRowNumberOfSheet(Sheet sheet, int rowNumber) { + int rowCount; + // =0 说明是初次调用 不是递归调用 + if (rowNumber == 0) { + rowCount = sheet.getLastRowNum(); + if (rowCount == 0) { + return 0; + } + } else { + rowCount = rowNumber; + } + // 如果有效行大于100行 那么就从上往下数 + if (rowCount > BoStringUtils.parseInt(EnumHelper.ExcelRowBoundary.getValue())) { + int realNum = 3; + for (int i = realNum; i < sheet.getLastRowNum() + 1; i++) { + Row row = sheet.getRow(i); + boolean isNullRow = true; + // 判断当前行 是不是有数据的行 + if (row != null) { + for (int j = 0; j < BoStringUtils.parseInt(EnumHelper.ExcelCellBoundary.getValue()) + && j < ExcelHelper.getLastCellNum(row); j++) { + if (row.getCell(j) != null && !"".equals(ExcelHelper.getCellValue(row.getCell(j)))) { + realNum++; + isNullRow = false; + break; + } + } + // 如果是无数据的空白行 + if (isNullRow) { + break; + } + } else { + // 无效行 + break; + } + } + return realNum; + } else { + // 获取最后一行 + Row row = sheet.getRow(rowCount); + boolean isNullRow = true; + if (row != null) { + for (int i = 0; i < BoStringUtils.parseInt(EnumHelper.ExcelCellBoundary.getValue()) + && i < ExcelHelper.getLastCellNum(row); i++) { + if (row.getCell(i) != null && !"".equals(ExcelHelper.getCellValue(row.getCell(i)))) { + isNullRow = false; + break; + } + } + } else { + if (rowCount < 0) { + return 0; + } + } + if (isNullRow) { + // 如果是无效行 + rowCount--; + if (row != null) { + // 就删掉这个无效行 + sheet.removeRow(row); + } + // 递归调用 继续数 + return ExcelHelper.getRowNumberOfSheet(sheet, rowCount); + } else { + return rowCount + 1; + } + } + } + + /** + * 生成模板 + * + * @param workbook + * @throws Exception + */ + public void generateSheet(Workbook workbook, List fileHeaders) throws Exception { + XSSFSheet sheet = (XSSFSheet) workbook.createSheet(); + Row row0 = sheet.createRow(0); + row0.setHeight((short) 400); + // 定义颜色 + CellStyle cellStyle = workbook.createCellStyle(); + // 填充模式 + cellStyle.setFillPattern(FillPatternType.DIAMONDS); + // 居中 + cellStyle.setAlignment(HorizontalAlignment.CENTER); + // 下边框 + cellStyle.setBorderBottom(BorderStyle.THIN); + // 左边框 + cellStyle.setBorderLeft(BorderStyle.THIN); + // 右边框 + cellStyle.setBorderRight(BorderStyle.THIN); + XSSFFont font = (XSSFFont) workbook.createFont(); + font.setFontName("仿宋_GB2312"); + font.setBold(true);// 粗体显示 + font.setFontHeightInPoints((short) 12); + cellStyle.setFont(font); + // 生成表头 + generateHeader(sheet, cellStyle, row0, fileHeaders); + // 设置文本格式以及调整列宽,使之能完整显示字段名称 + ExcelHelper.setTextformatAndColumnwidth(workbook); + } + + /** + * 生成表头 + * + * @param sheet + * @param cellStyle + * @param row0 + * @throws Exception + */ + private void generateHeader(XSSFSheet sheet, CellStyle cellStyle, Row row0, List fileHeaders) throws Exception { + Cell cell0 = null; + // 设置主机excel表头属性信息 + if (!ListTool.isEmpty(fileHeaders)) { + int index = 0; + for (String header : fileHeaders) { + cell0 = row0.createCell(index); + cell0.setCellValue(new ExcelFactory(row0).newRichTextString(header)); + cell0.setCellStyle(cellStyle); + sheet.setColumnWidth(index, 20 * 256); + index++; + } + } + } + + protected void validataWb(Workbook wb, List headers) throws Exception { + Sheet sheet = wb.getSheetAt(0); + Map header = readHeaders(sheet.getRow(0)); + validateHeader(header, headers); + } + + public static Map readHeaders(Row row) { + if (row == null) { + throw new RuntimeException("1、请检查是否是最新版本;\n" + "2、不要更改模板格式;\n" + "3、请重新下载模板;"); + } + Map header = new HashMap(30); + try { + for (int i = 0; i < ExcelHelper.getLastCellNum(row); i++) { + Cell cell = row.getCell(i); + // 有错误信息栏目 + if (cell != null && !"".equals(ExcelHelper.getCellValue(cell))) { + String value = ExcelHelper.getCellValue(cell); + header.put(value, new Integer(i)); + } + } + } catch (Exception e) { + log.error("检查表头报错", e); + throw new RuntimeException("1、请检查是否是最新版本;\n" + "2、不要更改模板格式;\n" + "3、请重新下载模板;\n"); + } + + return header; + } + + private void validateHeader(Map header, List headers) throws Exception { + Set propSetImport = new HashSet<>(); + Set propSetNew = new HashSet<>(); + for (String name : header.keySet()) { + propSetImport.add(name); + } + for (String property : headers) { + propSetNew.add(property); + } + Set propSetImportTemp = new HashSet<>(); + Set propSetNewTemp = new HashSet<>(); + propSetImportTemp.addAll(propSetImport); + propSetNewTemp.addAll(propSetNew); + + propSetImportTemp.removeAll(propSetNew); + if (!propSetImportTemp.isEmpty()) { + throw new Exception("表头中不应该包含无用信息:" + propSetImportTemp.toString()); + } + propSetNewTemp.removeAll(propSetImport); + if (!propSetNewTemp.isEmpty()) { + throw new Exception("表头中缺少以下属性:" + propSetNewTemp.toString()); + } + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/GraphAlgorithmUtils.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/GraphAlgorithmUtils.java new file mode 100644 index 0000000..4bdd7f3 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/GraphAlgorithmUtils.java @@ -0,0 +1,111 @@ +package com.bocloud.ams.service.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.collections.CollectionUtils; + +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.model.InstanceModel; +import com.bocloud.ams.entity.module.ModuleRelation; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/11 13:47 + */ +public class GraphAlgorithmUtils { + + /** + * 深度优先遍历(递归方式)--- 获取出度的路径 + */ + public static List> outDegreeGraphAlgorithm(ModuleRelation relation) { + List> result = new ArrayList<>(); + List path = new ArrayList<>(); + path.add(relation.getSourceId()); + findOutDegreePath(result, relation, path); + return result; + } + + private static void findOutDegreePath(List> result, ModuleRelation relation, List path) { + if (CollectionUtils.isEmpty(relation.getCmdbModuleRelationList())) { + result.add(path); + return; + } + for (ModuleRelation moduleRelation : relation.getCmdbModuleRelationList()) { + List cPath = new ArrayList<>(); + cPath.addAll(path); + cPath.add(moduleRelation.getTargetId()); + findOutDegreePath(result, moduleRelation, cPath); + } + } + + /** + * 深度优先遍历(递归方式)---- 获取入度的路径 + */ + public static List> penetrationGraphAlgorithm(ModuleRelation relation) { + List> result = new ArrayList<>(); + List path = new ArrayList<>(); + path.add(relation.getTargetId()); + findPenetrationPath(result, relation, path); + return result; + } + + private static void findPenetrationPath(List> result, ModuleRelation relation, List path) { + if (CollectionUtils.isEmpty(relation.getCmdbModuleRelationList())) { + result.add(path); + return; + } + for (ModuleRelation moduleRelation : relation.getCmdbModuleRelationList()) { + List cPath = new ArrayList<>(); + cPath.addAll(path); + cPath.add(moduleRelation.getSourceId()); + findPenetrationPath(result, moduleRelation, cPath); + } + } + + /** + * 深度优先遍历(递归方式)--- 获取路径 + */ + public static List> resourceInstanceAlgorithm(InstanceRelation relation, + Boolean pathDirection) { + List> result = new ArrayList<>(); + List path = new ArrayList<>(); + InstanceModel model = new InstanceModel(); + model.setModuleId(relation.getSourceModuleId()); + model.setModuleCode(relation.getSourceModuleCode()); + model.setInstanceId(relation.getSourceInstanceId()); + model.setInstanceName(relation.getSourceInstanceName()); + path.add(model); + resourceInstancePath(result, relation, path, pathDirection); + return result; + } + + private static void resourceInstancePath(List> result, InstanceRelation relation, + List path, Boolean pathDirection) { + if (CollectionUtils.isEmpty(relation.getCmdbInstanceRelations())) { + result.add(path); + return; + } + for (InstanceRelation instanceRelation : relation.getCmdbInstanceRelations()) { + List cPath = new ArrayList<>(); + cPath.addAll(path); + InstanceModel model = new InstanceModel(); + if (pathDirection) { + model.setModuleId(instanceRelation.getSourceModuleId()); + model.setModuleCode(instanceRelation.getSourceModuleCode()); + model.setInstanceId(instanceRelation.getSourceInstanceId()); + model.setInstanceName(instanceRelation.getSourceInstanceName()); + } else { + model.setModuleId(instanceRelation.getTargetModuleId()); + model.setModuleCode(instanceRelation.getTargetModuleCode()); + model.setInstanceId(instanceRelation.getTargetInstanceId()); + model.setInstanceName(instanceRelation.getTargetInstanceName()); + } + cPath.add(model); + resourceInstancePath(result, instanceRelation, cPath, pathDirection); + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceExcelHelper.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceExcelHelper.java new file mode 100644 index 0000000..dcee8ca --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceExcelHelper.java @@ -0,0 +1,646 @@ +package com.bocloud.ams.service.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.entity.module.Property; +import com.bocloud.ams.entity.module.PropertyItem; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.module.PropertyItemRepository; +import com.bocloud.ams.repository.module.PropertyRepository; +import com.google.common.collect.Maps; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +/** + * @ClassName: InstanceExportHelper + * @Description + * @Author yangzhenrong + * @Date 2022/5/25 14:26 + * @Version 1.0 + **/ +@Slf4j +@Component +public class InstanceExcelHelper { + + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private PropertyRepository propertyRepository; + @Autowired + private PropertyItemRepository propertyItemRepository; + + /*** + * 导出数据 + * + * @param wb + * @param properties + * @param instances + * @throws Exception + */ + public void generateDate(Workbook wb, List properties, List> instances) + throws Exception { + DataFormat format = wb.createDataFormat(); + CellStyle cellStyle = wb.createCellStyle(); +// cellStyle.setWrapText(true);// 自动换行 + // 设置文本格式 + cellStyle.setDataFormat(format.getFormat("@")); + Sheet sheet = wb.getSheetAt(0); + + Map header = ExcelHelper.readHeader4NameKey(sheet.getRow(0), 0); + Map propertyMap = Maps.newHashMap(); + Map propertyIndex = Maps.newHashMap(); + for (Property property : properties) { + Integer index = header.get(property.getName()); + propertyIndex.put(property.getCode(), index); + propertyMap.put(property.getCode(), property); + } + // 从第2行开始 + int rowNum = 1; + for (Map instance : instances) { + generateCellData(sheet, cellStyle, rowNum++, propertyIndex, propertyMap, instance); + } + } + + /*** + * 生成数据单元格 + * + * @param sheet + * @param cellStyle + * @param rowNum + * @param propertyIndex + * @param propertyMap + * @param instance + * @throws Exception + */ + protected void generateCellData(Sheet sheet, CellStyle cellStyle, int rowNum, Map propertyIndex, + Map propertyMap, Map instance) throws Exception { + // 生成行 + Row row = sheet.createRow(rowNum); + // 生成属性值 + generateInstanceValue(cellStyle, propertyIndex, propertyMap, instance, row); + } + + /*** + * 生成属性值 + * + * @param cellStyle + * @param propertyIndex + * @param propertyMap + * @param instance + * @param row + */ + private void generateInstanceValue(CellStyle cellStyle, Map propertyIndex, + Map propertyMap, Map instance, Row row) { + Cell cell; + for (Map.Entry entry : instance.entrySet()) { + Integer index = propertyIndex.get(entry.getKey()); + if (index != null) { + // 生成列 + cell = row.createCell(index); + if (propertyMap.containsKey(entry.getKey())) { + Property property = propertyMap.get(entry.getKey()); + String propertyType = property.getType(); + cell = row.createCell(index); + cell.setCellStyle(cellStyle); + Object value = entry.getValue(); + List propertyItems = property.getItemList(); + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + for (PropertyItem propertyItem : propertyItems) { + if (propertyItem.getValue().equals(entry.getValue())) { + value = propertyItem.getName(); + break; + } + } + } else if (null != value && (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType))) { + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getValue(), propertyItem); + } + String newValue = ""; + List values = JSONObject.parseArray(value.toString(), String.class); + for (String val : values) { + if (propertyItemMap.containsKey(val)) { + newValue += propertyItemMap.get(val).getName() + ","; + } + } + if(StringUtils.isNotEmpty(newValue)){ + value = newValue.substring(0, newValue.length() - 1); + }else { + value = newValue; + } + + } else if (null != value && (PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType))) { + JSONArray result = dealTableData(propertyItems, value); + value = result.toJSONString(); + } + cell.setCellValue(new ExcelFactory(row).newRichTextString((String) value)); + } + + } + } + } + + private JSONArray dealTableData(List propertyItems, Object value) { + + JSONArray targetArray = new JSONArray(); + if(null == value){ + return targetArray; + } + + Map propertyItemMap = new HashMap<>(); + for (PropertyItem propertyItem : propertyItems) { + propertyItemMap.put(propertyItem.getCode(), propertyItem); + } + try { + JSONArray array = JSONArray.parseArray(value.toString()); + + for (Object a : array) { + JSONObject obj = (JSONObject) JSON.toJSON(a); + JSONObject targetObj = new JSONObject(); + + for (String key : obj.keySet()) { + PropertyItem property = propertyItemMap.get(key); + String propertyType = property.getType(); + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + + for (PropertyItem propertyItem : property.getItemList()) { + if (propertyItem.getValue().equals(obj.getString(key))) { + targetObj.put(property.getName(), propertyItem.getName()); + break; + } + } + } else if (null != value && (PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType))) { + Map propertyItemValueMap = new HashMap<>(); + for (PropertyItem propertyItem : property.getItemList()) { + propertyItemValueMap.put(propertyItem.getValue(), propertyItem); + } + String newValue = ""; + List values = JSONObject.parseArray(obj.getString(key), String.class); + for (String val : values) { + if (propertyItemValueMap.containsKey(val)) { + newValue += propertyItemValueMap.get(val).getName() + ","; + } + } + + if (StringUtils.isNotEmpty(newValue)) { + targetObj.put(property.getName(), newValue.substring(0, newValue.length() - 1)); + } else { + targetObj.put(property.getName(), newValue); + } + + } else { + targetObj.put(property.getName(), obj.getString(key)); + } + } + + targetArray.add(targetObj); + + } + } catch (Exception e) { + log.error("表格数据格式异常", value); + } + + return targetArray; + + } + + /** + * 生成模板 + * + * @param wb + * @throws Exception + */ + public void generateSheet(Workbook wb, CiModule module, List properties) throws Exception { + String sheetName = module.getName() + "(" + module.getCode() + ")"; + Sheet sheet = wb.createSheet(sheetName); + // 第一行 属性名称 + Row row0 = sheet.createRow(0); + // 定义颜色 + CellStyle cellStyle = wb.createCellStyle(); + cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_BLUE.getIndex()); + // 填充模式 + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + // 居中 + cellStyle.setAlignment(HorizontalAlignment.CENTER); + // 下边框 + cellStyle.setBorderBottom(BorderStyle.THIN); + // 左边框 + cellStyle.setBorderLeft(BorderStyle.THIN); + // 右边框 + cellStyle.setBorderRight(BorderStyle.THIN); + XSSFFont font = (XSSFFont) wb.createFont(); + font.setFontName("仿宋_GB2312"); + font.setBold(true);// 粗体显示 + font.setFontHeightInPoints((short) 12); + cellStyle.setFont(font); + // 生成表头 + generateHeader(sheet, cellStyle, row0, properties); + // 设置文本格式以及调整列宽,使之能完整显示字段名称 + ExcelHelper.setTextformatAndColumnwidth(wb); + } + + protected void generateHeader(Sheet sheet, CellStyle cellStyle, Row row0, List properties) + throws Exception { + // 导出属性 + Cell cell0 = null; + // 列位置索引 + int index = 0; + for (Property property : properties) { + cell0 = row0.createCell(index); + cell0.setCellValue(new ExcelFactory(row0).newRichTextString(property.getName())); + cell0.setCellStyle(cellStyle); + sheet.setColumnWidth(index, 20 * 256); + index++; + } + } + + public void generateTemplateSheet(Workbook wb, CiModule module, List properties) throws Exception { + String sheetName = module.getName() + "(" + module.getCode() + ")"; + Sheet sheet = wb.createSheet(sheetName); + // 第一行 属性名称 + Row row0 = sheet.createRow(0); + // 第二行 属性说明 + Row row1 = sheet.createRow(1); + // 第三行 正文提示 + Row row2 = sheet.createRow(2); + // 定义颜色 + CellStyle cellStyle = wb.createCellStyle(); + cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.ROYAL_BLUE.getIndex()); + // 填充模式 + cellStyle.setFillPattern(FillPatternType.DIAMONDS); + // 居中 + cellStyle.setAlignment(HorizontalAlignment.CENTER); + // 下边框 + cellStyle.setBorderBottom(BorderStyle.THIN); + // 左边框 + cellStyle.setBorderLeft(BorderStyle.THIN); + // 右边框 + cellStyle.setBorderRight(BorderStyle.THIN); + + CellStyle cellStyle2 = wb.createCellStyle(); + cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_YELLOW.getIndex()); + // 填充模式 + cellStyle2.setFillPattern(FillPatternType.DIAMONDS); + // 居中 + cellStyle2.setAlignment(HorizontalAlignment.CENTER); + // 下边框 + cellStyle2.setBorderBottom(BorderStyle.THIN); + // 左边框 + cellStyle2.setBorderLeft(BorderStyle.THIN); + // 右边框 + cellStyle2.setBorderRight(BorderStyle.THIN); + + XSSFFont font = (XSSFFont) wb.createFont(); + font.setFontName("仿宋_GB2312"); + font.setBold(true);// 粗体显示 + font.setFontHeightInPoints((short) 12); + cellStyle.setFont(font); + cellStyle2.setFont(font); + // 生成表头 + generateTemplateHeader(sheet, cellStyle, cellStyle2, row0, row1, row2, properties); + // 设置文本格式以及调整列宽,使之能完整显示字段名称 + ExcelHelper.setTextformatAndColumnwidth(wb); + } + + protected void generateTemplateHeader(Sheet sheet, CellStyle cellStyle, CellStyle cellStyle2, Row row0, Row row1, + Row row2, List properties) throws Exception { + // 导出属性 + // 第一行 属性名称 + Cell cell0 = null; + // 第二行 属性说明 + Cell cell1 = null; + // 第三行 正文提示 + Cell cell2 = null; + + // 第一列给出提示start... + cell0 = row0.createCell(0); + cell0.setCellValue(new ExcelFactory(row0).newRichTextString("属性名称-->")); + cell0.setCellStyle(cellStyle); + + cell1 = row1.createCell(0); + cell1.setCellValue(new ExcelFactory(row1).newRichTextString("填写要求-->")); + cell1.setCellStyle(cellStyle); + + cell2 = row2.createCell(0); + cell2.setCellValue(new ExcelFactory(row2).newRichTextString("此行开始填写数据-->")); + cell2.setCellStyle(cellStyle); + sheet.setColumnWidth(0, "此行开始填写数据".getBytes().length * 256); + // 第一列给出提示end... + + // 列位置索引 + int index = 1; + for (Property property : properties) { + String propertyType = property.getType(); + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType) + || PropertyConstant.PropertyType.CHECKBOX.equals(propertyType) + || PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + List items = property.getItemList(); + property.setItemList(items); + } + cell0 = row0.createCell(index); + cell0.setCellValue(new ExcelFactory(row0).newRichTextString(property.getName())); + cell0.setCellStyle(cellStyle2); + + cell1 = row1.createCell(index); + cell1.setCellValue(new ExcelFactory(row1).newRichTextString(buildNoticeMsg(property))); + cell1.setCellStyle(cellStyle2); + // 多选下拉框暂不支持,以页面提示输入,以英文逗号分割 + if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + propertyItemCell(sheet, index, property); + } + // if (PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + // || PropertyConstant.PropertyType.CHECKBOX.equals(propertyType)) { + // propertyItemCell(sheet, index, property); + // } + index++; + } + } + + private void propertyItemCell(Sheet sheet, int index, Property property) throws Exception { + // 获取所有下拉值 + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + // 是否存在逗号 + Boolean flag = false; + String[] textlist = new String[items.size()]; + // 数据有效性的长度 + int veluesLength = 0; + int itemIndex = 0; + for (PropertyItem item : items) { + if (item.getName().contains(",")) { + flag = true; + } + textlist[itemIndex++] = item.getName(); + // 因为会追加逗号,所以+1 + veluesLength += item.getName().length() + 1; + } + if (veluesLength > 0 && veluesLength <= 255 && !flag) { + ExcelHelper.setValidation(sheet, textlist, 2, 65535, index, index, false); + } else if (veluesLength > 255 || flag) { + // 用新页 + ExcelHelper.setValidation(sheet, textlist, 2, 65535, index, index, true); + } + } + } + + /*** + * 构建属性提示语 + * + * @param property + * @return + */ + private String buildNoticeMsg(Property property) { + StringBuilder msg = new StringBuilder(); + try { + if (property.getIsRequired()) { + msg.append("必填;"); + } else { + msg.append("非必填;"); + } + if (null != property.getIsUniqued() && property.getIsUniqued()) { + msg.append("唯一性;"); + } + msg.append("格式["); + String propertyType = property.getType(); + if (PropertyConstant.PropertyType.TEXTFIELD.equals(propertyType)) { + msg.append("单行文本];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.TEXTAREA.equals(propertyType)) { + msg.append("多行文本];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.SINGLESELECT.equals(propertyType) + || PropertyConstant.PropertyType.RADIO.equals(propertyType)) { + msg.append("单选];"); + msg.append("可选值["); + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + for (int i = 0; i < items.size(); i++) { + msg.append(items.get(i).getName()); + if (i < items.size() - 1) { + msg.append(","); + } + } + msg.append("];"); + } + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + try { + if (CollectionUtils.isNotEmpty(items)) { + for (PropertyItem item : items) { + if (property.getDefaultValue().equals(item.getValue())) { + msg.append("默认值[" + item.getName() + "];"); + } + } + } + } catch (Exception e) { + log.error("设置默认值失败", e); + } + } + } else if (PropertyConstant.PropertyType.MULTISELECT.equals(propertyType) + || PropertyConstant.PropertyType.CHECKBOX.equals(propertyType)) { + msg.append("多选],"); + msg.append("可选值["); + List items = property.getItemList(); + if (CollectionUtils.isNotEmpty(items)) { + for (int i = 0; i < items.size(); i++) { + msg.append(items.get(i).getName()); + if (i < items.size() - 1) { + msg.append(","); + } + } + msg.append("];以英文逗号分割;"); + } + } else if (PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) + || PropertyConstant.PropertyType.MULTILINETABLE.equals(propertyType)) { + msg.append((PropertyConstant.PropertyType.SINGLELINETABLE.equals(propertyType) ? "单行" : "多行") + + "表格];填写JSON格式;"); + List items = property.getItemList(); + String propertyIds = property.getPropertyIds(); + Long linkModuleId = property.getLinkModuleId(); + StringBuilder tipMsg = new StringBuilder(); + if (StringUtils.isEmpty(propertyIds)) { + if (CollectionUtils.isNotEmpty(items)) { + msg.append("示例[{"); + tipMsg.append("示例说明[{"); + for (int i = 0; i < items.size(); i++) { + if (PropertyConstant.PropertyType.SINGLESELECT.equals(items.get(i).getType())) { + tipMsg.append("(单选)"); + List itemValObj = + JSONArray.parseArray(items.get(i).getItemValue(), JSONObject.class); + List newItemVals = new ArrayList<>(); + List newItemValTips = new ArrayList<>(); + for (JSONObject obj : itemValObj) { + String newObj2Tip = + "\"" + obj.getString("value") + "(" + obj.getString("name") + ")\""; + String newObj = "\"" + obj.getString("value") + "\""; + newItemValTips.add(newObj2Tip); + newItemVals.add(newObj); + } + tipMsg.append("\"" + items.get(i).getCode() + "(" + items.get(i).getName() + ")\":" + + newItemValTips); + if (CollectionUtils.isNotEmpty(newItemVals)) { + msg.append("\"" + items.get(i).getCode() + "\":" + newItemVals.get(0)); + } else { + msg.append("\"" + items.get(i).getCode() + "\":\"\""); + } + + } else if (PropertyConstant.PropertyType.MULTISELECT.equals(items.get(i).getType())) { + tipMsg.append("(多选)"); + List itemValObj = + JSONArray.parseArray(items.get(i).getItemValue(), JSONObject.class); + List newItemVals = new ArrayList<>(); + List newItemValTips = new ArrayList<>(); + for (JSONObject obj : itemValObj) { + String newObj2Tip = + "\"" + obj.getString("value") + "(" + obj.getString("name") + ")\""; + String newObj = "\"" + obj.getString("value") + "\""; + newItemValTips.add(newObj2Tip); + newItemVals.add(newObj); + } + tipMsg.append("\"" + items.get(i).getCode() + "(" + items.get(i).getName() + ")\":" + + newItemValTips); + msg.append("\"" + items.get(i).getCode() + "\":" + newItemVals); + } else { + tipMsg + .append("\"" + items.get(i).getCode() + "(" + items.get(i).getName() + ")\":\"\""); + msg.append("\"" + items.get(i).getCode() + "\":\"\""); + } + if (i < items.size() - 1) { + tipMsg.append(","); + msg.append(","); + } + } + tipMsg.append("}];"); + msg.append("}];"); + msg.append(tipMsg); + } + } else { + msg.append("示例[{"); + tipMsg.append("示例说明[{"); + String[] propertyIdsplit = propertyIds.split(","); + for (int i = 0; i < propertyIdsplit.length; i++) { + String propertyId = propertyIdsplit[i]; + Property object = propertyRepository.query(Long.valueOf(propertyId)); + if (null != object) { + if (PropertyConstant.PropertyType.SINGLESELECT.equals(object.getType()) + || PropertyConstant.PropertyType.MULTISELECT.equals(object.getType()) + || PropertyConstant.PropertyType.RADIO.equals(object.getType()) + || PropertyConstant.PropertyType.CHECKBOX.equals(object.getType())) { + List propertyItems = propertyItemRepository.queryByModuleId(linkModuleId); + if (CollectionUtils.isNotEmpty(propertyItems)) { + if (PropertyConstant.PropertyType.SINGLESELECT.equals(object.getType()) + || PropertyConstant.PropertyType.RADIO.equals(object.getType())) { + msg.append("(单选)"); + } + List newItemVals = new ArrayList<>(); + List newItemValTips = new ArrayList<>(); + for (PropertyItem propertyItem : propertyItems) { + String newObjTip = + "\"" + propertyItem.getCode() + "(" + propertyItem.getName() + ")\""; + String newObj = "\"" + propertyItem.getCode() + "\""; + newItemValTips.add(newObjTip); + newItemVals.add(newObj); + } + tipMsg.append( + "\"" + object.getCode() + "(" + object.getName() + ")\":" + newItemValTips); + msg.append("\"" + object.getCode() + "\":" + newItemVals); + } + } else { + tipMsg.append("\"" + object.getCode() + "(" + object.getName() + ")\":\"\""); + msg.append("\"" + object.getCode() + "\":\"\""); + } + } + if (i < propertyIdsplit.length - 1) { + tipMsg.append(","); + msg.append(","); + } + } + tipMsg.append("}];"); + msg.append("}];"); + msg.append(tipMsg); + } + + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.INTEGER.equals(propertyType)) { + msg.append("整数];"); + if (null != property.getMinValue()) { + msg.append("最小值[" + property.getMinValue() + "];"); + } + if (null != property.getMaxValue()) { + msg.append("最大值[" + property.getMaxValue() + "];"); + } + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.FLOAT.equals(propertyType)) { + msg.append("数字];"); + if (null != property.getDecimalNum()) { + msg.append("小数位数[" + property.getDecimalNum() + "];"); + } + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.BOOLEAN.equals(propertyType)) { + msg.append("布尔值];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.JSON.equals(propertyType)) { + msg.append("JSON格式];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.DATE.equals(propertyType)) { + msg.append("日期];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.TIME.equals(propertyType)) { + msg.append("时间];"); + if (StringUtils.isNotEmpty(property.getDefaultValue())) { + msg.append("默认值[" + property.getDefaultValue() + "];"); + } + } else if (PropertyConstant.PropertyType.TEXTENCRYPT.equals(propertyType)) { + msg.append("加密,仅创建人能看到属性值];"); + } + + if (StringUtils.isNotEmpty(property.getUnit())) { + msg.append("单位[" + property.getUnit() + "];"); + } + if (null != property.getLength() && property.getLength() > 0) { + msg.append("长度限制[" + property.getLength() + "]字符;"); + } + return msg.toString(); + } catch (Exception e) { + msg.append(e.getMessage()); + } + return msg.toString(); + + } + + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceHistoryHelper.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceHistoryHelper.java new file mode 100644 index 0000000..5a128f4 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/InstanceHistoryHelper.java @@ -0,0 +1,170 @@ +package com.bocloud.ams.service.utils; + +import com.bocloud.ams.entity.enums.InstanceEnum; +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceHistory; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.entity.module.CiModule; +import com.bocloud.ams.repository.instance.InstanceHistoryRepository; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.module.ModuleRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; +import com.megatron.common.utils.Common; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * @ClassName: CmdbInstanceHistoryHelper + * @Description模型实例变更记录工具类 + * @Author yangzhenrong + * @Date 2022/5/17 11:07 + * @Version 1.0 + **/ +@Slf4j +@Component("instanceHistoryHelper") +public class InstanceHistoryHelper { + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private InstanceHistoryRepository instanceHistoryRepository; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + @Autowired + private ModuleRepository moduleRepository; + @Autowired + private RedisTemplate redisTemplate; + + public void history(Object object, String catalog, String category, Long operator) { + try { + String userName = redisTemplate.opsForValue().get("User_Name_" + operator); + StringBuffer content = new StringBuffer(); + InstanceEnum.category historyCategory = InstanceEnum.category.valueOf(category); + Long instanceId = null; + Long moduleId = null; + if (InstanceEnum.catalog.INSTANCE.name().equals(catalog)) { + Instance instance = (Instance) object; + instanceId = instance.getId(); + moduleId = instance.getModuleId(); + CiModule module = moduleRepository.query(moduleId); + if (null == module) { + log.error("模型不存在"); + return; + } + String moduleName = module.getName(); + String instanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + instance.getModuleCode().toLowerCase(); + InstanceValue instanceValue = instanceValueRepository.query(instanceValueTable, Common.NAME, instanceId); + if (null == instanceValue) { + log.error("模型实例缺少关键属性[name]"); + return; + } + String instanceName = instanceValue.getPropertyValue(); + switch (historyCategory) { + case CREATE: + content.append("新增实例:" + moduleName + "-" + instanceName); + break; + case MODIFY: + content.append("修改实例:" + moduleName + "-" + instanceName); + break; + case DEL: + content.append("删除实例:" + moduleName + "-" + instanceName); + break; + default: + break; + } + } + if (InstanceEnum.catalog.RELATION.name().equals(catalog)) { + InstanceRelation instanceRelation = (InstanceRelation) object; + Long sourceInstanceId = instanceRelation.getSourceInstanceId(); + Long sourceModuleId = instanceRelation.getSourceModuleId(); + + //源 + instanceId = sourceInstanceId; + moduleId = sourceModuleId; + + Long targetInstanceId = instanceRelation.getTargetInstanceId(); + Long targetModuleId = instanceRelation.getTargetModuleId(); + CiModule sourceModule = moduleRepository.query(sourceModuleId); + CiModule targetModule = moduleRepository.query(targetModuleId); + if (null == sourceModule || null == targetModule) { + log.error("关联关系中的模型不存在"); + return; + } + String sourceModuleName = sourceModule.getName(); + String targetModuleName = targetModule.getName(); + + String sourceInstanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + instanceRelation.getSourceModuleCode().toLowerCase(); + String targetInstanceValueTable = CmdbUtils.CMDB_INSTANCE_VALUE + instanceRelation.getTargetModuleCode().toLowerCase(); + InstanceValue sourceInstanceValue = instanceValueRepository.query(sourceInstanceValueTable, Common.NAME, sourceInstanceId); + InstanceValue targetInstanceValue = instanceValueRepository.query(targetInstanceValueTable, Common.NAME, targetInstanceId); + if (null == sourceInstanceValue || null == targetInstanceValue) { + log.error("模型实例关系的源实例或目标实例缺少关键属性[name]"); + return; + } + String instanceRelationName = instanceRelation.getModuleRelationName(); + String sourceInstanceName = sourceInstanceValue.getPropertyValue(); + String targetInstanceName = targetInstanceValue.getPropertyValue(); + switch (historyCategory) { + case CREATE: + content.append("新增实例关系:[" + sourceModuleName + "-" + sourceInstanceName + "]与[" + targetModuleName + "-" + targetInstanceName + "]关联:[" + instanceRelationName + "]"); + break; + case MODIFY: + content.append("修改实例关系:[" + sourceModuleName + "-" + sourceInstanceName + "]与[" + targetModuleName + "-" + targetInstanceName + "]关联:[" + instanceRelationName + "]"); + break; + case DEL: + content.append("取消实例关系:[" + sourceModuleName + "-" + sourceInstanceName + "]与[" + targetModuleName + "-" + targetInstanceName + "]关联:[" + instanceRelationName + "]"); + break; + default: + break; + } + } + InstanceHistory instanceHistory = new InstanceHistory(moduleId, instanceId, catalog, category, content.toString(), userName, new Date()); + instanceHistoryRepository.save(instanceHistory); + } catch (Exception e) { + log.error("变更记录保存失败:", e); + } + } + + public InstanceHistory getInstanceHistory(Instance instance, CiModule module, InstanceValue instanceNameValue, String catalog, String category, Long operator) { + + InstanceHistory instanceHistory = null; + try { + String userName = redisTemplate.opsForValue().get("User_Name_" + operator); + StringBuffer content = new StringBuffer(); + InstanceEnum.category historyCategory = InstanceEnum.category.valueOf(category); + Long instanceId = instance.getId(); + Long moduleId = instance.getModuleId(); + String moduleName = module.getName(); + String instanceName = instanceNameValue.getPropertyValue(); + switch (historyCategory) { + case CREATE: + content.append("新增实例:" + moduleName + "-" + instanceName); + break; + case MODIFY: + content.append("修改实例:" + moduleName + "-" + instanceName); + break; + case DEL: + content.append("删除实例:" + moduleName + "-" + instanceName); + break; + case BATCH_MODIFY: + content.append("批量编辑:" + moduleName + "-" + instanceName); + break; + case BATCH_DELETE: + content.append("批量删除:" + moduleName + "-" + instanceName); + break; + default: + break; + } + instanceHistory = new InstanceHistory(moduleId, instanceId, catalog, category, content.toString(), userName, new Date()); + } catch (Exception e) { + log.error("获取实例操作历史失败",e); + } + return instanceHistory; + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/JsonCompareUtil.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/JsonCompareUtil.java new file mode 100644 index 0000000..4da9c10 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/JsonCompareUtil.java @@ -0,0 +1,248 @@ +package com.bocloud.ams.service.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @Description: json比较工具 + * @Title: JsonCompareUtil + * @Author: majiali + * @CreateTime: 2022/6/8 15:10 + */ +public class JsonCompareUtil { + + public static boolean campareJsonString(String oldJsonStr, String newJsonStr1) { + //将字符串转换为json对象 + JSON oldJson = JSON.parseObject(oldJsonStr); + JSON newJson = JSON.parseObject(newJsonStr1); + //递归遍历json对象所有的key-value,将其封装成path:value格式进⾏⽐较 + Map oldMap = new LinkedHashMap<>(); + Map newMap = new LinkedHashMap<>(); + convertJsonToMap(oldJson, "", oldMap); + convertJsonToMap(newJson, "", newMap); + Map differenceMap = campareMap(oldMap, newMap); + //将最终的⽐较结果把不相同的转换为json对象返回 + JSONObject jsonObject = convertMapToJson(differenceMap); + return jsonObject.isEmpty(); + } + + public JSONObject campareJsonObject(String oldJsonStr, String newJsonStr1) { + //将字符串转换为json对象 + JSON oldJson = JSON.parseObject(oldJsonStr); + JSON newJson = JSON.parseObject(newJsonStr1); + //递归遍历json对象所有的key-value,将其封装成path:value格式进⾏⽐较 + Map oldMap = new LinkedHashMap<>(); + Map newMap = new LinkedHashMap<>(); + convertJsonToMap(oldJson, "", oldMap); + convertJsonToMap(newJson, "", newMap); + Map differenceMap = campareMap(oldMap, newMap); + //将最终的⽐较结果把不相同的转换为json对象返回 + JSONObject jsonObject = convertMapToJson(differenceMap); + return jsonObject; + } + + /** + * 将json数据转换为map存储⽤于⽐较 + * + * @param json + * @param root + * @param resultMap + */ + private static void convertJsonToMap(Object json, String root, Map resultMap) { + if (json instanceof JSONObject) { + JSONObject jsonObject = ((JSONObject) json); + Iterator iterator = jsonObject.keySet().iterator(); + while (iterator.hasNext()) { + Object key = iterator.next(); + Object value = jsonObject.get(key); + String newRoot = "".equals(root) ? key + "" : root + "." + key; + if (value instanceof JSONObject || value instanceof JSONArray) { + convertJsonToMap(value, newRoot, resultMap); + } else { + resultMap.put(newRoot, value); + } + } + } else if (json instanceof JSONArray) { + JSONArray jsonArray = (JSONArray) json; + for (int i = 0; i < jsonArray.size(); i++) { + Object vaule = jsonArray.get(i); + String newRoot = "".equals(root) ? "[" + i + "]" : root + ".[" + i + "]"; + if (vaule instanceof JSONObject || vaule instanceof JSONArray) { + convertJsonToMap(vaule, newRoot, resultMap); + } else { + resultMap.put(newRoot, vaule); + } + } + } + } + + /** + * ⽐较两个map,返回不同数据 + * + * @param oldMap + * @param newMap + * @return + */ + private static Map campareMap(Map oldMap, Map newMap) { + //遍历newMap,将newMap的不同数据装进oldMap,同时删除oldMap中与newMap相同的数据 + campareNewToOld(oldMap, newMap); + //将旧的有新的沒有的数据封数据结果存在就的里⾯ + campareOldToNew(oldMap); + return oldMap; + } + + /** + * 将旧的有新的沒有的数据封数据结果存在就的里⾯ + * + * @param oldMap + * @return + */ + private static void campareOldToNew(Map oldMap) { + //统⼀oldMap中newMap不存在的数据的数据结构,便于解析 + for (Iterator> it = oldMap.entrySet().iterator(); it.hasNext(); ) { + Map.Entry item = it.next(); + String key = item.getKey(); + Object value = item.getValue(); + int lastIndex = key.lastIndexOf("."); + if (!(value instanceof Map)) { + Map differenceMap = new HashMap<>(); + differenceMap.put("oldValue", value); + differenceMap.put("newValue", ""); + oldMap.put(key, differenceMap); + } + } + } + + /** + * 将新的map与旧的⽐較,并将数据統⼀存在旧的里⾯ + * + * @param oldMap + * @param newMap + * @return + */ + private static void campareNewToOld(Map oldMap, Map newMap) { + for (Iterator> it = newMap.entrySet().iterator(); it.hasNext(); ) { + Map.Entry item = it.next(); + String key = item.getKey(); + Object newValue = item.getValue(); + Map differenceMap = new HashMap<>(); + int lastIndex = key.lastIndexOf("."); + //String lastPath = key.substring(lastIndex + 1).toLowerCase(); + if (oldMap.containsKey(key)) { + Object oldValue = oldMap.get(key); + if (newValue.equals(oldValue)) { + if (newValue.equals(oldValue)) { + oldMap.remove(key); + continue; + } else { + differenceMap.put("oldValue", oldValue); + differenceMap.put("newValue", newValue); + oldMap.put(key, differenceMap); + } + } else { + differenceMap.put("oldValue", ""); + differenceMap.put("newValue", newValue); + oldMap.put(key, differenceMap); + } + } + } + } + + /** + * 将已经找出不同数据的map根据key的层级结构封装成json返回 + * + * @param map + * @return + */ + private static JSONObject convertMapToJson(Map map) { + JSONObject resultJSONObject = new JSONObject(); + for (Iterator> it = map.entrySet().iterator(); it.hasNext(); ) { + Map.Entry item = it.next(); + String key = item.getKey(); + Object value = item.getValue(); + String[] paths = key.split("\\."); + int i = 0; + Object remarkObject = null; + int indexAll = paths.length - 1; + while (i <= paths.length - 1) { + String path = paths[i]; + if (i == 0) { + //初始化对象标识 + if (resultJSONObject.containsKey(path)) { + remarkObject = resultJSONObject.get(path); + } else { + if (indexAll > i) { + if (paths[i + 1].matches("\\[[0-9]+\\]")) { + remarkObject = new JSONArray(); + } else { + remarkObject = new JSONObject(); + } + resultJSONObject.put(path, remarkObject); + } else { + resultJSONObject.put(path, value); + } + } + i++; + continue; + } + //匹配集合对象 + if (path.matches("\\[[0-9]+\\]")) { + int startIndex = path.lastIndexOf("["); + int endIndext = path.lastIndexOf("]"); + int index = Integer.parseInt(path.substring(startIndex + 1, endIndext)); + if (indexAll > i) { + if (paths[i + 1].matches("\\[[0-9]+\\]")) { + while (((JSONArray) remarkObject).size() <= index) { + if (((JSONArray) remarkObject).size() == index) { + ((JSONArray) remarkObject).add(index, new JSONArray()); + } else { + ((JSONArray) remarkObject).add(null); + } + } + } else { + while (((JSONArray) remarkObject).size() <= index) { + if (((JSONArray) remarkObject).size() == index) { + ((JSONArray) remarkObject).add(index, new JSONObject()); + } else { + ((JSONArray) remarkObject).add(null); + } + } + } + remarkObject = ((JSONArray) remarkObject).get(index); + } else { + while (((JSONArray) remarkObject).size() <= index) { + if (((JSONArray) remarkObject).size() == index) { + ((JSONArray) remarkObject).add(index, value); + } else { + ((JSONArray) remarkObject).add(null); + } + } + } + } else { + if (indexAll > i) { + if (paths[i + 1].matches("\\[[0-9]+\\]")) { + if (!((JSONObject) remarkObject).containsKey(path)) { + ((JSONObject) remarkObject).put(path, new JSONArray()); + } + } else { + if (!((JSONObject) remarkObject).containsKey(path)) { + ((JSONObject) remarkObject).put(path, new JSONObject()); + } + } + remarkObject = ((JSONObject) remarkObject).get(path); + } else { + ((JSONObject) remarkObject).put(path, value); + } + } + i++; + } + } + return resultJSONObject; + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ModuleConstant.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ModuleConstant.java new file mode 100644 index 0000000..2903bb6 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/ModuleConstant.java @@ -0,0 +1,28 @@ +package com.bocloud.ams.service.utils; + +/** + * @Description: 模型相关常量 + * @Title: ModuleConstant + * @Author: majiali + * @CreateTime: 2022/5/12 9:36 + */ +public class ModuleConstant { + + /** + * @Description:模型关系约束条件 1 + */ + public static final String RELATION_TYPE_1 = "1"; + /** + * @Description:模型关系约束条件 N + */ + public static final String RELATION_TYPE_N = "N"; + + /** + * 模型状态-启用 + */ + public static final String STATUS_ENABLE = "ENABLE"; + /** + * 模型状态-禁用 + */ + public static final String STATUS_DISABLED = "DISABLED"; +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/PropertyConstant.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/PropertyConstant.java new file mode 100644 index 0000000..30f887d --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/PropertyConstant.java @@ -0,0 +1,107 @@ +package com.bocloud.ams.service.utils; + +import java.util.Arrays; +import java.util.List; + + +/** + * @Description: 属性值类型常量 + * @Author: majiali + * @CreateTime: 2022/5/6 10:12 + */ +public class PropertyConstant { + + public static final String DATA_ALL_AUTH_MANAGER_ID_KEY = "data_all_auth_manager_id"; + + public static final String GLOBALLY_UNIQUE_IDENTIFIER = "GLOBALLYUNIQUEIDENTIFIER"; + + public static final List RESERVED_MODULE_CODES = + Arrays.asList("id", "uuid", "name", "gmt_create", "gmt_modify", "is_deleted", + "module_id", "creator_id", "mender_id", "module_code", DATA_ALL_AUTH_MANAGER_ID_KEY); + + + /** + * @Description: 属性池表格引入类型 + */ + public static final String TABLE_TYPE_ONE = "1"; + /** + * @Description: 属性池表格自定义 + */ + public static final String TABLE_TYPE_ZERO = "0"; + + + /** + * @Description: 属性池/属性 值类型 + */ + public class PropertyType { + //单行文本 + public static final String TEXTFIELD = "TEXTFIELD"; + + //多行文本 + public static final String TEXTAREA = "TEXTAREA"; + + //下拉单选 + public static final String SINGLESELECT = "SINGLESELECT"; + + //下拉多选 + public static final String MULTISELECT = "MULTISELECT"; + + /** + * 单选 + */ + public static final String RADIO = "RADIO"; + /** + * 多选 + */ + public static final String CHECKBOX = "CHECKBOX"; + + //引用 + public static final String QUOTE = "QUOTE"; + + //日期 + public static final String DATE = "DATE"; + + //时间 + public static final String TIME = "TIME"; + + //数据加密 + public static final String TEXTENCRYPT = "TEXTENCRYPT"; + + //整数 + public static final String INTEGER = "INTEGER"; + + //小数 + public static final String FLOAT = "FLOAT"; + + //单行表格 + public static final String SINGLELINETABLE = "SINGLELINETABLE"; + + //多行表格 + public static final String MULTILINETABLE = "MULTILINETABLE"; + + //json + public static final String JSON = "JSON"; + + //布尔值 + public static final String BOOLEAN = "BOOLEAN"; + + } + + //默认值类型 + public class DefaultValueType { + + //固定值:FIXED + public static final String FIXED = "FIXED"; + + //内置函数:INNERFUN + public static final String INNERFUN = "INNERFUN"; + + //自增ID:AUTOINCRID + public static final String AUTOINCRID = "AUTOINCRID"; + + //流水号:SERIALNUM + public static final String SERIALNUM = "SERIALNUM"; + } + + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RelationHistoryConstant.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RelationHistoryConstant.java new file mode 100644 index 0000000..829999a --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RelationHistoryConstant.java @@ -0,0 +1,74 @@ +package com.bocloud.ams.service.utils; + +/** + * @Description: 关联历史类型常量 + * @Author: majiali + * @CreateTime: 2022/6/8 10:12 + */ +public class RelationHistoryConstant { + + /** + * 待调和记录预检失败,数据冲突错误提示 + */ + public static String RECONCILED_ERROR_MSG = "因该待调和记录的资源实例关系与目前库中已存在的资源实例关系产生矛盾,系统自动取消数据调和任务"; + public static String CANCEL_ERROR_MSG = "手动取消数据调和任务"; + public static String NO_MODULE_ERROR_MSG = "因未查询到模型关系相关信息,系统自动取消数据调和任务"; + public static String NO_INSTANCE_RELATION_ERROR_MSG = "因未查询到实例关系相关信息,系统自动取消数据调和任务"; + public static String NO_INSTANCE_ERROR_MSG = "因未查询到实例相关信息,系统自动取消数据调和任务"; + + /** + * @Description: 状态 + */ + public enum Status { + //成功 + SUCCESS("SUCCESS"), + //失败 + FAILED("FAILED"), + //待调和 + RECONCILED("RECONCILED"); + private final String value; + + Status(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + //操作类型 + public enum Type { + //取消关联 + CANCEL("CANCEL"), + //关联 + RELATION("RELATION"); + private final String value; + + Type(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + //关联方式 + public enum Way { + //手动 + MANUAL("MANUAL"), + //自动 + AUTO("AUTO"); + private final String value; + + Way(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RepositoryHandler.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RepositoryHandler.java new file mode 100644 index 0000000..e7d4bc0 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/RepositoryHandler.java @@ -0,0 +1,123 @@ +package com.bocloud.ams.service.utils; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.bocloud.ams.entity.instance.Instance; +import com.bocloud.ams.entity.instance.InstanceRelation; +import com.bocloud.ams.entity.instance.InstanceValue; +import com.bocloud.ams.repository.instance.InstanceRelationRepository; +import com.bocloud.ams.repository.instance.InstanceRepository; +import com.bocloud.ams.repository.instance.InstanceValueRepository; +import com.bocloud.ams.repository.utils.CmdbUtils; + +/** + * @ClassName: RepositoryHandler + * @Description 动态修改类Table注解值,及保存或修改数据 + * @Author yangzhenrong + * @Date 2022/5/27 18:48 + * @Version 1.0 + **/ +@Component +public class RepositoryHandler { + @Autowired + private InstanceRepository instanceRepository; + @Autowired + private InstanceValueRepository instanceValueRepository; + @Autowired + private InstanceRelationRepository instanceRelationRepository; + + public void saveInstance(Instance instance, String tableName) { + synchronized (Instance.class) { + CmdbUtils.changeTableAnnotationValue(Instance.class, tableName); + instanceRepository.save(instance); + } + } + + public void saveInstanceValue(InstanceValue instanceValue, String tableName) { + synchronized (InstanceValue.class) { + CmdbUtils.changeTableAnnotationValue(InstanceValue.class, tableName); + instanceValueRepository.save(instanceValue); + } + + } + + public void saveInstanceRelation(InstanceRelation instanceRelation, String tableName) { + synchronized (InstanceRelation.class) { + CmdbUtils.changeTableAnnotationValue(InstanceRelation.class, tableName); + instanceRelationRepository.save(instanceRelation); + } + + } + + public void batchSaveInstance(List instances, String tableName) { + synchronized (Instance.class) { + CmdbUtils.changeTableAnnotationValue(Instance.class, tableName); + instanceRepository.batchSave(instances, 100); + } + } + + public void batchSaveInstanceValue(List instanceValues, String tableName) { + synchronized (InstanceValue.class) { + CmdbUtils.changeTableAnnotationValue(InstanceValue.class, tableName); + instanceValueRepository.batchSave(instanceValues, 100); + } + + } + + public void batchSaveInstanceRelation(List instanceRelations, String tableName) { + synchronized (InstanceRelation.class) { + CmdbUtils.changeTableAnnotationValue(InstanceRelation.class, tableName); + instanceRelationRepository.batchSave(instanceRelations, 100); + } + + } + + public void updateInstance(Instance instance, String tableName) { + synchronized (Instance.class) { + CmdbUtils.changeTableAnnotationValue(Instance.class, tableName); + instanceRepository.update(instance); + } + } + + public void updateInstanceValue(InstanceValue instanceValue, String tableName) { + synchronized (InstanceValue.class) { + CmdbUtils.changeTableAnnotationValue(InstanceValue.class, tableName); + instanceValueRepository.update(instanceValue); + } + + } + + public void updateInstanceRelation(InstanceRelation instanceRelation, String tableName) { + synchronized (InstanceRelation.class) { + CmdbUtils.changeTableAnnotationValue(InstanceRelation.class, tableName); + instanceRelationRepository.update(instanceRelation); + } + + } + + public void batchUpdateInstance(List instances, String tableName) { + synchronized (Instance.class) { + CmdbUtils.changeTableAnnotationValue(Instance.class, tableName); + instanceRepository.batchUpdate(instances, 100); + } + } + + public void batchUpdateInstanceValue(List instanceValues, String tableName) { + synchronized (InstanceValue.class) { + CmdbUtils.changeTableAnnotationValue(InstanceValue.class, tableName); + instanceValueRepository.batchUpdate(instanceValues, 100); + } + + } + + public void batchUpdateInstanceRelation(List instanceRelations, String tableName) { + synchronized (InstanceRelation.class) { + CmdbUtils.changeTableAnnotationValue(InstanceRelation.class, tableName); + instanceRelationRepository.batchUpdate(instanceRelations, 100); + } + + } +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/StreamUtils.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/StreamUtils.java new file mode 100644 index 0000000..088de05 --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/StreamUtils.java @@ -0,0 +1,24 @@ +package com.bocloud.ams.service.utils; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * @author huliwei + * @date 2023/1/5 + */ +public class StreamUtils { + + /** + * 根据属性去重 + * @param function + * @param + * @return + */ + public static Predicate distinctByKey(Function function){ + Map map = new HashMap<>(); + return t -> map.putIfAbsent(function.apply(t),Boolean.TRUE) == null; + } + +} diff --git a/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/paginationUtil.java b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/paginationUtil.java new file mode 100644 index 0000000..6101e1a --- /dev/null +++ b/bocloud.ams.service/src/main/java/com/bocloud/ams/service/utils/paginationUtil.java @@ -0,0 +1,51 @@ +package com.bocloud.ams.service.utils; + +import org.apache.commons.collections.CollectionUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author 胡立伟 + * @program: bocloud.ams + * @description: + * @date 2022/5/18 13:49 + */ +public class paginationUtil { + /** + * 内存分页 + * + * @param records 待分页的数据 + * @param pageNum 当前页码 + * @param pageSize 每页显示的条数 + * @return 分页之后的数据 + */ + public static Map pagination(List records, int pageNum, int pageSize) { + Map map=new HashMap<>(); + if (CollectionUtils.isEmpty(records)) { + return null; + } + int totalCount = records.size(); + int remainder = totalCount % pageSize; + int pageCount = (remainder > 0) ? totalCount / pageSize + 1 : totalCount / pageSize; + map.put("totalCount",totalCount); + map.put("pageCount",pageCount); + map.put("pageNo",pageNum); + map.put("pageSize",pageSize); + if (remainder == 0) { + map.put("list",records.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList())); + return map; + } else { + if (pageNum == pageCount) { + map.put("list", records.stream().skip((pageNum - 1) * pageSize).limit(totalCount).collect(Collectors.toList())); + return map; + } else { + map.put("list",records.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList())); + return map; + } + } + } + +} diff --git a/bocloud.ams.task/.gitignore b/bocloud.ams.task/.gitignore new file mode 100644 index 0000000..e313482 --- /dev/null +++ b/bocloud.ams.task/.gitignore @@ -0,0 +1,10 @@ +*/target/* +*/.settings/* +*.classpath +*.project +*.prefs +*.class +*.iml +/.idea/* +*/.svn/* +/target/ diff --git a/bocloud.ams.task/pom.xml b/bocloud.ams.task/pom.xml new file mode 100644 index 0000000..7484869 --- /dev/null +++ b/bocloud.ams.task/pom.xml @@ -0,0 +1,28 @@ + + + + bocloud.ams + com.bocloud + 6.5.0-LTS-SZ + + 4.0.0 + bocloud.ams.task + + + com.bocloud + bocloud.ams.entity + + + com.bocloud + bocloud.boot.common + + + + com.oracle + ojdbc6 + 1.0 + + + \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Module.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Module.java new file mode 100644 index 0000000..bca65a4 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Module.java @@ -0,0 +1,16 @@ +/** + * + */ +package com.bocloud.ams.task.annotation; + +import java.lang.annotation.*; + +/** + * Worker类型 主要包括:脚本,文件,资源,软件,方法,数据,运维 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface Module { + String code() default "task.maintain.scirpt"; +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Worker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Worker.java new file mode 100644 index 0000000..fd28ade --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/annotation/Worker.java @@ -0,0 +1,13 @@ +/** + * + */ +package com.bocloud.ams.task.annotation; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface Worker { + String name() default ""; +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/exception/NodeFormatException.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/exception/NodeFormatException.java new file mode 100644 index 0000000..e920fda --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/exception/NodeFormatException.java @@ -0,0 +1,30 @@ +package com.bocloud.ams.task.exception; + +/** + * 任务节点参数异常 + */ +public class NodeFormatException extends Exception { + + private static final long serialVersionUID = 1L; + + public NodeFormatException() { + super("任务节点参数异常!"); + } + + public NodeFormatException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public NodeFormatException(String message, Throwable cause) { + super(message, cause); + } + + public NodeFormatException(String message) { + super(message); + } + + public NodeFormatException(Throwable cause) { + super(cause); + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/RemoteWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/RemoteWorker.java new file mode 100644 index 0000000..3268d92 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/RemoteWorker.java @@ -0,0 +1,217 @@ +package com.bocloud.ams.task.executor; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.model.HostResult; +import com.bocloud.ams.task.model.Module; +import com.bocloud.ams.task.model.WorkerHost; +import com.bocloud.cmp.boot.model.BoCloudExchange; +import com.megatron.common.enums.PostDataFormat; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.IDFactory; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.http.model.RemoteService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.Binding.DestinationType; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.core.RabbitAdmin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * 远端配置任务执行线程,用来支持任务执行能分发的对某个worker的请求操作 + * + * @author dmw + */ +@Slf4j +public class RemoteWorker implements Callable> { + private static final String EXCHANGE = BoCloudExchange.Default.DIRECT.getExchange(); + private static final Map arguments = MapTools.simpleMap("x-ha-policy", "all"); + private static final Integer DEFAULT_TIMEOUT = 1000 * 60 * 10; + private static final String QUEUE = "queue"; + private static final String TIMEOUT = "timeout"; + private List targets; + + // 默认超时时间是10分钟 + private Integer timeout; + // worker返回任务结果的队列 + private String callback; + private boolean sync = false; + private RemoteService service; + private RabbitAdmin rabbitAdmin; + + /** + * 构造函数 + * + * @param service worker服务实例 + * @param rabbitAdmin RabbitMQ管理实例 + * @param timeout 超时时间 单位为S + * @throws NodeFormatException + */ + public RemoteWorker(RemoteService service, RabbitAdmin rabbitAdmin, Integer timeout, String callback, boolean sync) + throws NodeFormatException { + this.service = service; + this.rabbitAdmin = rabbitAdmin; + if (null == timeout) { + this.timeout = DEFAULT_TIMEOUT; + } else { + this.timeout = timeout * 1000; + } + this.callback = callback; + this.sync = sync; + init(); + } + + @Override + public GeneralResult call() throws Exception { + if (null == service || !service.isExist()) { + log.error("remote worker does not exist!"); + return handleError("远程Worker服务不存在"); + } + if (sync) { + return handleSync(); + } else { + return handleAsync(); + } + } + + /** + * 处理同步调用 + * + * @return + */ + @SuppressWarnings("unchecked") + private GeneralResult handleSync() { + log.info("start to sync call remote worker [{}] and timeout is :{} ms ", service.getUrl(), timeout); + Map params = (Map) service.getParam().getParams(); + if (null == params) { + params = new HashMap(); + } + params.put("timeout", this.timeout / 1000); + service.getParam().setParams(params); + GeneralResult invoke = service.invoke(); + if (log.isDebugEnabled()) { + log.debug("remote worker response is {}", invoke); + } + return handleResult(invoke); + } + + /** + * 处理异步调用 + * + * @return + */ + @SuppressWarnings("unchecked") + private GeneralResult handleAsync() { + if (StringUtils.isEmpty(callback)) { + this.callback = IDFactory.instance().uuid(); + } + GeneralResult result; + Map params = (Map) service.getParam().getParams(); + if (null == params) { + params = new HashMap(); + } + Object object = params.get("module"); + if (null == object) { + log.info("start to async call remote worker [{}] with callback queue is [{}] and timeout is :{}ms", + service.getUrl(), this.callback, timeout); + } else { + Module module = (Module) object; + log.info( + "start to async call remote worker [{}] with callback queue is [{}] and task module is [{}] and timeout is :{}ms", + service.getUrl(), this.callback, module.getName(), timeout); + } + try { + params.put(QUEUE, this.callback); + service.getParam().setParams(params); + // 声明worker结果的存放队列并将其绑定到指定的exchange:bocloud.direct.exchange + rabbitAdmin.declareQueue(new Queue(this.callback, false, false, true, arguments)); + rabbitAdmin + .declareBinding(new Binding(this.callback, DestinationType.QUEUE, EXCHANGE, this.callback, arguments)); + log.info("request params is {}", JSONObject.toJSON(service.getParam().getParams())); + GeneralResult invoke = service.invoke(); + if (invoke.isFailed()) { + log.error("invoke remote worker [{}] failed for : {}", service.getUrl(), invoke.getMessage()); + return handleError(invoke.getMessage()); + } + // 这里说明请求成功发送到worker上,接下来可以等待结果消息了 + Message message = rabbitAdmin.getRabbitTemplate().receive(callback, timeout + 60 * 1000); + if (null == message) { + log.error("get callback from remote worker by queue [{}] timeout", callback); + result = handleError("获取任务结果消息超时!"); + } else { + String content = new String(message.getBody(), "UTF-8"); + log.info("get result [{}] from remote worker by queue [{}]", content, callback); + if (log.isDebugEnabled()) { + log.debug("callback from remote worker is :\n{}", content); + } + try { + result = handleResult(JSONObject.parseObject(content, GeneralResult.class)); + } catch (Exception e) { + log.error("callback data transfer exception!", e); + result = handleError("返回数据格式异常!"); + } + } + } catch (Exception e) { + log.error("等待Worker 【{}】返回任务结果消息异常:", service.getUrl(), e); + result = handleError(e.getMessage()); + } finally { + rabbitAdmin.deleteQueue(this.callback); + } + if (log.isDebugEnabled()) { + log.debug("执行结果: {}", result); + } + return result; + } + + /** + * 构建消息 + * + * @param invoke 远程调用结果 + * @return + * @throws NodeFormatException + */ + private GeneralResult handleResult(GeneralResult invoke) { + if (invoke.isSuccess()) { + return invoke; + } + if (null == invoke.getData()) { + return handleError(invoke.getMessage()); + } else { + return invoke; + } + } + + private GeneralResult handleError(String message) { + List hostResults = new ArrayList<>(); + for (WorkerHost target : targets) { + hostResults.add(new HostResult(false, message, target.getHost(), target.getRawName(), target.getPort(), + target.getUser())); + } + return new GeneralResult<>(false, hostResults, message); + } + + @SuppressWarnings("unchecked") + private void init() throws NodeFormatException { + Map params = (Map) service.getParam().getParams(); + if (null == params) { + params = new HashMap(); + } + params.put(TIMEOUT, timeout / 1000); + params.put(QUEUE, this.callback); + service.getParam().setParams(params); + service.setDataFormat(PostDataFormat.RAW); + String targetParam = JSONObject.toJSONString(params.get("targets")); + targets = WorkerHost.parseTargets(targetParam); + if (targets.isEmpty()) { + throw new NodeFormatException("目标机器参数信息格式错误"); + } + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/TaskJobSubmit.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/TaskJobSubmit.java new file mode 100644 index 0000000..66da83a --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/TaskJobSubmit.java @@ -0,0 +1,46 @@ +package com.bocloud.ams.task.executor; + +import com.bocloud.ams.task.listener.MaintainTaskListener; +import com.bocloud.ams.task.model.Job; +import com.bocloud.ams.task.model.JobResult; +import com.bocloud.ams.task.model.enums.TaskParam; +import com.bocloud.cmp.boot.model.BoCloudExchange; +import com.megatron.common.utils.Common; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; + +/** + * @Author liuyuanyuan + * @Date 2022/6/9 0009 13:42 + * @Description: + */ +@Slf4j +@Component +public class TaskJobSubmit { + @Autowired + private MaintainTaskListener maintainTaskListener; + @Autowired + private AmqpTemplate amqpTemplate; + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + public Boolean subJob(Job job) { + log.info("任务提交 【{}】," + System.currentTimeMillis(), job.getParam(Common.NAME)); + try { + taskExecutor.execute(() -> { + String type = job.getParam(TaskParam.TASKTYPE.name()); + if ("maintain".equalsIgnoreCase(type)) { + JobResult jobResult = maintainTaskListener.onTask(job); + amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "cmdb.task.result.queue", jobResult); + } + }); + return true; + } catch (Exception e) { + log.error("Task delivery failure:", e); + return false; + } + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/WorkerDispatcher.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/WorkerDispatcher.java new file mode 100644 index 0000000..c0e2378 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/executor/WorkerDispatcher.java @@ -0,0 +1,162 @@ +package com.bocloud.ams.task.executor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.springframework.amqp.rabbit.core.RabbitAdmin; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.model.HostResult; +import com.bocloud.cmp.boot.model.BoCloudService; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.core.Service; +import com.megatron.framework.http.core.HttpMethod; +import com.megatron.framework.http.core.ServiceFactory; +import com.megatron.framework.http.model.RemoteService; + +import lombok.extern.slf4j.Slf4j; + +/** + * 远程Worker调用任务分发器,用来对worker请求进行参数校验和请求分片调度。 + * + * @author dmw + */ +@Slf4j +public class WorkerDispatcher { + private static final String URL = "/api/gaia/v1/job/submit"; + private static final Service SERVICE = Service.create(BoCloudService.GAIA.getName()); + private Map headers = MapTools.simpleMap("Content-Type", "application/json"); + private ExecutorService executor = null; + private CompletionService> completionService = null; + + private ServiceFactory serviceFactory; + private RabbitAdmin rabbitAdmin; + + /** + * + */ + public WorkerDispatcher() { + super(); + } + + /** + * 构造方法 + * + * @param serviceFactory + * @param rabbitAdmin + */ + public WorkerDispatcher(ServiceFactory serviceFactory, RabbitAdmin rabbitAdmin) { + this.serviceFactory = serviceFactory; + this.rabbitAdmin = rabbitAdmin; + } + + /** + * worker任务分发执行 + * + * @return + * @throws NodeFormatException + */ + public GeneralResult execute(List> params, Integer timeout) throws NodeFormatException { + log.info("start to execute multiful remote worker dispatch ..."); + if (null == params || params.isEmpty()) { + log.error("remote worker param is empty!"); + throw new NodeFormatException("worker param is illegel!"); + } + List hostResults = new ArrayList<>(); + int corePoolSize = params.size() + 1; + executor = new ThreadPoolExecutor(corePoolSize, corePoolSize, 30, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(corePoolSize), (Runnable runnable) -> { + return new Thread(runnable); + }); + completionService = new ExecutorCompletionService<>(executor); + if (serviceFactory.exist(SERVICE).isFailed()) { + log.error("remote worker does not exist!"); + return GeneralResult.FAILED("远程Worker不存在!"); + } + for (Map param : params) { + RemoteService service = serviceFactory.build(SERVICE, URL, HttpMethod.OPERATE, headers, param); + RemoteWorker task = new RemoteWorker(service, rabbitAdmin, timeout, null, false); + completionService.submit(task); + } + int finished = 0; + int workerNum = params.size(); + // 处理任务执行的结果 + GeneralResult GeneralResult = null; + boolean hasError = false; + while (finished < workerNum) { + try { + GeneralResult = completionService.take().get(); + if (GeneralResult.isFailed()) { + // 单次任务请求处理失败! + log.error("Worker任务执行失败!{}", GeneralResult.getMessage()); + hasError = true; + } + hostResults.addAll(buildHostResult(GeneralResult)); + } catch (Exception e) { + log.error("单次请求worker任务执行异常", e); + hasError = true; + } + finished++; + } + // TODO 这里需要处理失败重试机制,后续优化 + if (null != executor) { + executor.shutdown(); + } + if (hasError) { + log.error("task of execute failed!"); + if (ListTool.isEmpty(hostResults)) { + hostResults.addAll(buildHostResult(params, false, "任务执行失败:可能所设定时间已经超时")); + } + return new GeneralResult<>(false, hostResults, "任务执行失败:可能所设定时间已经超时"); + } else { + // 没有失败任务,直接返回处理结果 + log.info("task of execute success!"); + return new GeneralResult<>(true, hostResults, "任务执行成功!"); + } + } + + private List buildHostResult(GeneralResult result) { + List hostResults = new ArrayList<>(); + if (null != result.getData()) { + try { + hostResults = JSONArray.parseArray(JSONObject.toJSONString(result.getData()), HostResult.class); + } catch (Exception e) { + log.error("build host result error!", e); + } + } + return hostResults; + } + + private List buildHostResult(List> params, Boolean success, String message) { + List hostResults = new ArrayList<>(); + for (Map param : params) { + if (null == param.get("targets")) { + continue; + } + try { + List results = + JSONArray.parseArray(JSONObject.toJSONString(param.get("targets")), HostResult.class); + for (HostResult result : results) { + result.setSuccess(success); + result.setMessage(message); + } + hostResults.addAll(results); + } catch (Exception e) { + log.error("build host result error!", e); + } + } + return hostResults; + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/DBInput.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/DBInput.java new file mode 100644 index 0000000..83c5d25 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/DBInput.java @@ -0,0 +1,19 @@ +package com.bocloud.ams.task.input; + +import com.bocloud.ams.task.annotation.Module; +import com.bocloud.ams.task.model.DBFront; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 11:32 2018/12/26 @ Modified + * By: + */ +@Module(code = "task.maintain.database") +public class DBInput extends Input { + + public DBInput(DBFront dbFront, Target target, Depend depend) { + super(dbFront, target, depend); + } + + public DBInput() { + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Depend.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Depend.java new file mode 100644 index 0000000..d6e8ef2 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Depend.java @@ -0,0 +1,77 @@ +package com.bocloud.ams.task.input; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 10:57 2018/12/17 @ Modified + * By: + */ +public class Depend { + private String key; + private String desp; + private Object value; + private Source source; + + static enum Source { + Internal, External; + } + + /** + * @return the key + */ + public String getKey() { + return key; + } + + /** + * @param key + * the key to set + */ + public void setKey(String key) { + this.key = key; + } + + /** + * @return the desp + */ + public String getDesp() { + return desp; + } + + /** + * @param desp + * the desp to set + */ + public void setDesp(String desp) { + this.desp = desp; + } + + /** + * @return the value + */ + public Object getValue() { + return value; + } + + /** + * @param value + * the value to set + */ + public void setValue(Object value) { + this.value = value; + } + + /** + * @return the source + */ + public Source getSource() { + return source; + } + + /** + * @param source + * the source to set + */ + public void setSource(Source source) { + this.source = source; + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/HttpInput.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/HttpInput.java new file mode 100644 index 0000000..eca2aad --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/HttpInput.java @@ -0,0 +1,22 @@ +package com.bocloud.ams.task.input; + +import com.bocloud.ams.task.annotation.Module; +import com.bocloud.ams.task.model.HttpFront; + +/** + * @ Description: + * @ Author :丁明威 + * @ Date :Created in 11:33 2018/12/26 + * @ Modified By: + */ +@Module(code = "task.maintain.method") +public class HttpInput extends Input { + + public HttpInput(HttpFront httpFront, Target target, Depend depend) { + super(httpFront, target, depend); + } + + public HttpInput() { + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Input.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Input.java new file mode 100644 index 0000000..4838af2 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Input.java @@ -0,0 +1,46 @@ +package com.bocloud.ams.task.input; + +/** + * @ Description:任务输入抽象封装类 + * @ Author :丁明威 + * @ Date :Created in 10:54 2018/12/17 + * @ Modified By: + */ +public abstract class Input { + private Fronts fronts; + private Target target; + private Depend depend; + + public Input() { + } + + public Input(Fronts fronts, Target target, Depend depend) { + this.fronts = fronts; + this.target = target; + this.depend = depend; + } + + public Fronts getFronts() { + return fronts; + } + + public void setFronts(Fronts fronts) { + this.fronts = fronts; + } + + public Target getTarget() { + return target; + } + + public void setTarget(Target target) { + this.target = target; + } + + public Depend getDepend() { + return depend; + } + + public void setDepend(Depend depend) { + this.depend = depend; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/ScriptInput.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/ScriptInput.java new file mode 100644 index 0000000..c84a2f8 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/ScriptInput.java @@ -0,0 +1,21 @@ +package com.bocloud.ams.task.input; + + +import com.bocloud.ams.task.annotation.Module; +import com.bocloud.ams.task.model.ScriptFront; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 10:48 2018/12/26 @ Modified + * By: + */ +@Module(code = "task.maintain.script") +public class ScriptInput extends Input { + + public ScriptInput() { + super(); + } + + public ScriptInput(ScriptFront scriptFront, Target target, Depend depend) { + super(scriptFront, target, depend); + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Target.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Target.java new file mode 100644 index 0000000..a5176f8 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/input/Target.java @@ -0,0 +1,94 @@ +package com.bocloud.ams.task.input; + +import java.util.List; + +import com.bocloud.ams.task.model.WorkerHost; + +/** + * @ Description:任务执行目标主机或者设备 @ Author :丁明威 @ Date :Created in 10:31 + * 2018/12/17 @ Modified By: + */ +public class Target { + private Boolean sudo; + private Boolean become; + private String becomeUser; + private String becomePass; + private Integer identId; + private List data; + private String authenMode; + private String becomeMethod; + + public Target(Boolean sudo, Integer identId, List data, String authenMode) { + this.sudo = sudo; + this.identId = identId; + this.data = data; + this.authenMode = authenMode; + } + + public Target() { + } + + public String getBecomeMethod() { + return becomeMethod; + } + + public void setBecomeMethod(String becomeMethod) { + this.becomeMethod = becomeMethod; + } + + public Boolean getSudo() { + return sudo; + } + + public void setSudo(Boolean sudo) { + this.sudo = sudo; + } + + public Boolean getBecome() { + return become; + } + + public void setBecome(Boolean become) { + this.become = become; + } + + public String getBecomeUser() { + return becomeUser; + } + + public void setBecomeUser(String becomeUser) { + this.becomeUser = becomeUser; + } + + public String getBecomePass() { + return becomePass; + } + + public void setBecomePass(String becomePass) { + this.becomePass = becomePass; + } + + public Integer getIdentId() { + return identId; + } + + public void setIdentId(Integer identId) { + this.identId = identId; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getAuthenMode() { + return authenMode; + } + + public void setAuthenMode(String authenMode) { + this.authenMode = authenMode; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/AbstractTaskListener.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/AbstractTaskListener.java new file mode 100644 index 0000000..e030c2e --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/AbstractTaskListener.java @@ -0,0 +1,47 @@ +package com.bocloud.ams.task.listener; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.model.Job; +import com.bocloud.ams.task.model.JobResult; +import com.bocloud.ams.task.model.enums.TaskParam; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.Common; + +/** + * 抽象任务监听器 + */ +public abstract class AbstractTaskListener { + static final String QUEUE = TaskParam.QUEUE.name(); + static final String DATA = TaskParam.TASKDATA.name(); + static final String PJOB = TaskParam.TASKPJOB.name(); + static final String CODE = TaskParam.TASKCODE.name(); + static final String TIME = TaskParam.TIMEOUT.name(); + static final String TYPE = TaskParam.TASKTYPE.name(); + static final String NAME = Common.NAME; + + /** + * 处理接收到任务时的逻辑 + * + * @param job + * 接受到的任务参数对象 + * @return 任务执行结果 + */ + public abstract JobResult onTask(Job job); + + Integer buildTimeout(String time) { + Integer timeout; + try { + timeout = Integer.valueOf(time); + if (timeout <= 0) { + timeout = 600; + } + } catch (Exception e) { + timeout = 600; + } + return timeout; + } + + public JobResult buildResult(GeneralResult result, Job job) { + return new JobResult(result.isSuccess(), JSONObject.toJSONString(result), job); + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/MaintainTaskListener.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/MaintainTaskListener.java new file mode 100644 index 0000000..0ea3e72 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/listener/MaintainTaskListener.java @@ -0,0 +1,58 @@ +package com.bocloud.ams.task.listener; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.model.Job; +import com.bocloud.ams.task.model.JobResult; +import com.bocloud.ams.task.utils.ParamBuilder; +import com.bocloud.ams.task.worker.AbstractWorker; +import com.bocloud.ams.task.worker.WorkerFactory; +import com.megatron.common.model.GeneralResult; + +import lombok.extern.slf4j.Slf4j; + +/** + * 运维类任务监听器 + */ +@Slf4j +@Component +public class MaintainTaskListener extends AbstractTaskListener { + private final WorkerFactory workerFactory; + private ParamBuilder paramBuilder; + + @Autowired + public MaintainTaskListener(WorkerFactory workerFactory) { + this.workerFactory = workerFactory; + this.paramBuilder = new ParamBuilder(); + } + + @Override + public JobResult onTask(Job job) { + String code = job.getParam(CODE); + String name = job.getParam(NAME); + String data = job.getParam(DATA); + String time = job.getParam(TIME); + log.info("receive a maintain task! name is: {} ,code is :{}", name, code); + try { + AbstractWorker worker = workerFactory.buildWorker(code, buildTimeout(time)); + Object param = paramBuilder.buildParam(code, data); + if (null == worker) { + log.error("maintain worker [{}] instance build error!", code); + throw new NodeFormatException("worker instance build error!"); + } + if (null == param) { + log.error("maintain worker [{}] param build error!", code); + throw new NodeFormatException("worker param build error!"); + } + return buildResult(worker.execute(param), job); + } catch (NodeFormatException e) { + log.error("maintain worker param {} is illegal", code); + return buildResult(GeneralResult.FAILED(e.getLocalizedMessage()), job); + } catch (Exception e) { + log.error("maintain worker occur unknown exception!", e); + return buildResult(GeneralResult.FAILED(e.getMessage()), job); + } + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/DBFront.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/DBFront.java new file mode 100644 index 0000000..138bff9 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/DBFront.java @@ -0,0 +1,122 @@ +package com.bocloud.ams.task.model; + +import com.bocloud.ams.task.utils.DBDriver; +import com.megatron.common.model.GeneralResult; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 11:27 2018/12/26 @ Modified By: + */ +public class DBFront { + private String category; + private String driver; + private String database; + private Long scriptId; + private List groupId; + private String jdbcUrl; + private String username; + private String password; + private String content; + + public DBFront(String category, String driver, Long scriptId, List groupId, String jdbcUrl, String username, + String password, String content, String database) { + this.category = category; + this.driver = driver; + this.scriptId = scriptId; + this.groupId = groupId; + this.jdbcUrl = jdbcUrl; + this.username = username; + this.password = password; + this.content = content; + this.database = database; + } + + public DBFront() { + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public DBDriver getDBDriver() throws Exception { + if (StringUtils.isEmpty(database)) { + throw new Exception("database driver is null!"); + } + GeneralResult hasResult = DBDriver.has(database); + if (hasResult.isFailed()) { + throw new Exception("no specific driver found!"); + } else { + return hasResult.getData(); + } + } + + public String getDriver() { + return driver; + } + + public void setDriver(String driver) { + this.driver = driver; + } + + public Long getScriptId() { + return scriptId; + } + + public void setScriptId(Long scriptId) { + this.scriptId = scriptId; + } + + public List getGroupId() { + return groupId; + } + + public void setGroupId(List groupId) { + this.groupId = groupId; + } + + public String getJdbcUrl() { + return jdbcUrl; + } + + public void setJdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HostResult.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HostResult.java new file mode 100644 index 0000000..57fec52 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HostResult.java @@ -0,0 +1,166 @@ +package com.bocloud.ams.task.model; + +import com.alibaba.fastjson.JSONArray; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.megatron.common.model.Result; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * 目标机器或者HTTP请求的url或者DB的连接URL的执行结果信息封装类 + * + * @author dmw + */ +public class HostResult extends Result { + + private Long id; + private String host;// 这里可以表示远程目标机器,还可以表示远程服务的URL,或者数据库连接的URL + private Double cost; + private String rawName; + private Integer port; + private String user; + private String task; // worker当前执行的任务名 + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the host + */ + public String getHost() { + return host; + } + + /** + * @param host the host to set + */ + public void setHost(String host) { + this.host = host; + } + + /** + * @return the cost + */ + public Double getCost() { + return cost; + } + + /** + * @param cost the cost to set + */ + public void setCost(Double cost) { + this.cost = cost; + } + + /** + * @return the rawName + */ + public String getRawName() { + return rawName; + } + + /** + * @param rawName the rawName to set + */ + public void setRawName(String rawName) { + this.rawName = rawName; + } + + /** + * @return the port + */ + public Integer getPort() { + return port; + } + + /** + * @param port the port to set + */ + public void setPort(Integer port) { + this.port = port; + } + + /** + * @return the user + */ + public String getUser() { + return user; + } + + /** + * + */ + public HostResult() { + super(); + } + + /** + * @param user the user to set + */ + public void setUser(String user) { + this.user = user; + } + + public String getTask() { + return task; + } + + public void setTask(String task) { + this.task = task; + } + + /** + * @param success + * @param message + */ + public HostResult(boolean success, String message) { + super(success, message); + } + + /** + * @param success + * @param message + */ + public HostResult(boolean success, String message, String host) { + super(success, message); + this.host = host; + } + + public HostResult(boolean success, String message, String host, String rawName, Integer port, String user) { + super(success, message); + this.host = host; + this.rawName = rawName; + this.port = port; + this.user = user; + } + + /** + * @param host + */ + public HostResult(String host) { + this.host = host; + } + + public static List convertList(String content) throws NodeFormatException { + if (StringUtils.isEmpty(content)) { + throw new NodeFormatException("参数为空!"); + } + try { + return JSONArray.parseArray(content, HostResult.class); + } catch (Exception e) { + throw new NodeFormatException("目标主机任务结果参数异常1", e); + } + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HttpFront.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HttpFront.java new file mode 100644 index 0000000..8817b34 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/HttpFront.java @@ -0,0 +1,84 @@ +package com.bocloud.ams.task.model; + + +import com.megatron.common.enums.HttpRequestMethod; +import com.megatron.common.enums.PostDataFormat; + +import java.util.Map; + +/** + * @ Description: + * @ Author :丁明威 + * @ Date :Created in 11:20 2018/12/26 + * @ Modified By: + */ +public class HttpFront { + private String url; + private String body; + private PostDataFormat format; + private HttpRequestMethod method; + private Map headers; + private Map params; + + + public HttpFront(String url, String body, PostDataFormat format, HttpRequestMethod method, + Map headers, Map params) { + this.url = url; + this.body = body; + this.format = format; + this.method = method; + this.headers = headers; + this.params = params; + } + + public HttpFront() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public PostDataFormat getFormat() { + return format; + } + + public void setFormat(PostDataFormat format) { + this.format = format; + } + + public HttpRequestMethod getMethod() { + return method; + } + + public void setMethod(HttpRequestMethod method) { + this.method = method; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Job.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Job.java new file mode 100644 index 0000000..004d6de --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Job.java @@ -0,0 +1,156 @@ +package com.bocloud.ams.task.model; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class Job { + + private String taskId; + private Integer priority = 100; + private String submitNodeGroup; + private String taskTrackerNodeGroup; + private Map extParams; + private boolean needFeedback = false; + private int maxRetryTimes = 0; + private String cronExpression; + private int repeatCount = 0; + private Long repeatInterval; + private Long triggerTime; + private boolean replaceOnExist = false; + private boolean relyOnPrevCycle = true; + + public Integer getPriority() { + return priority; + } + + public void setPriority(Integer priority) { + this.priority = priority; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getSubmitNodeGroup() { + return submitNodeGroup; + } + + public void setSubmitNodeGroup(String submitNodeGroup) { + this.submitNodeGroup = submitNodeGroup; + } + + public String getTaskTrackerNodeGroup() { + return taskTrackerNodeGroup; + } + + public void setTaskTrackerNodeGroup(String taskTrackerNodeGroup) { + this.taskTrackerNodeGroup = taskTrackerNodeGroup; + } + + public boolean isNeedFeedback() { + return needFeedback; + } + + public void setNeedFeedback(boolean needFeedback) { + this.needFeedback = needFeedback; + } + + public Map getExtParams() { + return extParams; + } + + public void setExtParams(Map extParams) { + this.extParams = extParams; + } + + public String getParam(String key) { + if (extParams == null) { + return null; + } + return extParams.get(key); + } + + public void setParam(String key, String value) { + if (extParams == null) { + extParams = new HashMap(); + } + extParams.put(key, value); + } + + public String getCronExpression() { + return cronExpression; + } + + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; + } + + public boolean isCron() { + return this.cronExpression != null && !"".equals(this.cronExpression.trim()); + } + + public boolean isRepeatable() { + return (this.repeatInterval != null && this.repeatInterval > 0) + && (this.repeatCount >= -1 && this.repeatCount != 0); + } + + public void setTriggerDate(Date date) { + if (date != null) { + this.triggerTime = date.getTime(); + } + } + + public Long getTriggerTime() { + return triggerTime; + } + + public void setTriggerTime(Long triggerTime) { + this.triggerTime = triggerTime; + } + + public boolean isReplaceOnExist() { + return replaceOnExist; + } + + public void setReplaceOnExist(boolean replaceOnExist) { + this.replaceOnExist = replaceOnExist; + } + + public int getMaxRetryTimes() { + return maxRetryTimes; + } + + public void setMaxRetryTimes(int maxRetryTimes) { + this.maxRetryTimes = maxRetryTimes; + } + + public int getRepeatCount() { + return repeatCount; + } + + public void setRepeatCount(int repeatCount) { + this.repeatCount = repeatCount; + } + + public Long getRepeatInterval() { + return repeatInterval; + } + + public void setRepeatInterval(Long repeatInterval) { + this.repeatInterval = repeatInterval; + } + + public boolean isRelyOnPrevCycle() { + return relyOnPrevCycle; + } + + public void setRelyOnPrevCycle(boolean relyOnPrevCycle) { + this.relyOnPrevCycle = relyOnPrevCycle; + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/JobResult.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/JobResult.java new file mode 100644 index 0000000..3d77b54 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/JobResult.java @@ -0,0 +1,68 @@ +package com.bocloud.ams.task.model; + +import com.alibaba.fastjson.JSON; + +public class JobResult { + + private Job job; + private boolean success; + private String msg; + private Long time; + private String exeSeqId; + + public JobResult() { + super(); + } + + public JobResult(boolean success, String msg, Job job) { + super(); + this.success = success; + this.msg = msg; + this.job = job; + } + + public Job getJob() { + return job; + } + + public void setJob(Job job) { + this.job = job; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public Long getTime() { + return time; + } + + public void setTime(Long time) { + this.time = time; + } + + public String getExeSeqId() { + return exeSeqId; + } + + public void setExeSeqId(String exeSeqId) { + this.exeSeqId = exeSeqId; + } + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Module.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Module.java new file mode 100644 index 0000000..9d5b728 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Module.java @@ -0,0 +1,77 @@ +package com.bocloud.ams.task.model; + +/** + * @author dmw + */ +public class Module { + + private String name; + private Entity args; + private Option options; + + /** + * @param name + * @param args + */ + public Module(String name, Entity args) { + this.name = name; + this.args = args; + } + + public Module(String name, Entity args, Option options) { + this.name = name; + this.args = args; + this.options = options; + } + + /** + * @param name + */ + public Module(String name) { + this.name = name; + } + + /** + * + */ + public Module() { + super(); + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the args + */ + public Entity getArgs() { + return args; + } + + /** + * @param args the args to set + */ + public void setArgs(Entity args) { + this.args = args; + } + + public Option getOptions() { + return options; + } + + public void setOptions(Option options) { + this.options = options; + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Option.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Option.java new file mode 100644 index 0000000..937ac49 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/Option.java @@ -0,0 +1,88 @@ +package com.bocloud.ams.task.model; + +/** + * @author dmw + */ +public class Option { + + private Boolean sudo; + private Boolean become; + private String becomeUser; + private String becomePass; + private String becomeMethod; + + public Option() { + super(); + } + + public Option(boolean sudo) { + super(); + this.sudo = sudo; + } + + public Option(Boolean sudo, Boolean become) { + this.sudo = sudo; + this.become = become; + } + + public Option(Boolean sudo, Boolean become, String becomeUser, String becomePass, String becomeMethod) { + super(); + this.sudo = sudo; + this.become = become; + this.becomeUser = becomeUser; + this.becomePass = becomePass; + this.becomeMethod = becomeMethod; + } + + public Boolean getSudo() { + return sudo; + } + + public void setSudo(Boolean sudo) { + this.sudo = sudo; + } + + public Boolean getBecome() { + return become; + } + + public void setBecome(Boolean become) { + this.become = become; + } + + /** + * @return the becomeUser + */ + public String getBecomeUser() { + return becomeUser; + } + + public String getBecomeMethod() { + return becomeMethod; + } + + public void setBecomeMethod(String becomeMethod) { + this.becomeMethod = becomeMethod; + } + + /** + * @param becomeUser the becomeUser to set + */ + public void setBecomeUser(String becomeUser) { + this.becomeUser = becomeUser; + } + + /** + * @return the becomePass + */ + public String getBecomePass() { + return becomePass; + } + + /** + * @param becomePass the becomePass to set + */ + public void setBecomePass(String becomePass) { + this.becomePass = becomePass; + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/ScriptFront.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/ScriptFront.java new file mode 100644 index 0000000..5c7b825 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/ScriptFront.java @@ -0,0 +1,73 @@ +package com.bocloud.ams.task.model; + +import java.util.List; + +/** + * @ Description:脚本执行前端输入 + * @ Author :丁明威 + * @ Date :Created in 10:52 2018/12/26 + * @ Modified By: + */ +public class ScriptFront { + //脚本分组ID + private List groupId; + //脚本数据库中的ID + private Long scriptId; + //脚本执行参数 + private String params; + //脚本内容 + private String content; + //脚本类别:shell|bat 等 + private String category; + + public ScriptFront(List groupId, Long scriptId, String params, String content, String category) { + this.groupId = groupId; + this.scriptId = scriptId; + this.params = params; + this.content = content; + this.category = category; + } + + public ScriptFront() { + } + + public List getGroupId() { + return groupId; + } + + public void setGroupId(List groupId) { + this.groupId = groupId; + } + + public Long getScriptId() { + return scriptId; + } + + public void setScriptId(Long scriptId) { + this.scriptId = scriptId; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/TargetGroup.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/TargetGroup.java new file mode 100644 index 0000000..acb0eb7 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/TargetGroup.java @@ -0,0 +1,59 @@ +package com.bocloud.ams.task.model; + +import java.util.List; + +/** + * 目标机器分组,用来整体封装Linux和Windows类型的目标机器 + * + * @author dmw + */ +public class TargetGroup { + + private List windows; + + private List linuxs; + + /** + * @param windows + * @param linuxs + */ + public TargetGroup(List windows, List linuxs) { + this.windows = windows; + this.linuxs = linuxs; + } + + /** + * + */ + public TargetGroup() { + super(); + } + + /** + * @return the windows + */ + public List getWindows() { + return windows; + } + + /** + * @param windows the windows to set + */ + public void setWindows(List windows) { + this.windows = windows; + } + + /** + * @return the linuxs + */ + public List getLinuxs() { + return linuxs; + } + + /** + * @param linuxs the linuxs to set + */ + public void setLinuxs(List linuxs) { + this.linuxs = linuxs; + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerHost.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerHost.java new file mode 100644 index 0000000..f3cb7a6 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerHost.java @@ -0,0 +1,240 @@ +package com.bocloud.ams.task.model; + +import com.bocloud.ams.task.exception.NodeFormatException; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.megatron.common.enums.OSCategory; +import com.megatron.common.model.GeneralResult; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * Worker请求目标封装类 + * + * @author dmw + */ +public class WorkerHost { + + private Long id; + private String host;// 主机IP + private String user;// 操作账号 + private String pasd;// 账号密码 + private Integer port;// SSH端口,默认22 + private String task;// 关联的任务名称 + private String rawName;// 主机名称 + private String category = OSCategory.LINUX.name();// 操作系统类型,默认Linux + private String sequenceId; + private String connection; + private String pkey; + private Boolean sudo; + private Long segmentId; + + public WorkerHost() { + super(); + } + + public WorkerHost(String host, String connection) { + super(); + this.host = host; + this.connection = connection; + } + + public WorkerHost(String host, String user, String pasd, Integer port, OSCategory category) { + super(); + this.host = host; + this.user = user; + this.pasd = pasd; + this.category = category.name(); + if (null == port || 0 >= port) { + switch (category) { + case WINDOWS: + this.port = 5985; + break; + case LINUX: + this.port = 22; + break; + case UNIX: + this.port = 22; + break; + default: + this.port = 22; + break; + } + } else { + this.port = port; + } + } + + public WorkerHost(Long id, String host, String user, String pasd, Integer port, OSCategory category) { + super(); + this.id = id; + this.host = host; + this.user = user; + this.pasd = pasd; + this.category = category.name(); + if (null == port || 0 >= port) { + switch (category) { + case WINDOWS: + this.port = 5985; + break; + case LINUX: + this.port = 22; + break; + case UNIX: + this.port = 22; + break; + default: + this.port = 22; + break; + } + } else { + this.port = port; + } + } + + public static GeneralResult parseTarget(String content) { + GeneralResult result = null; + if (StringUtils.isEmpty(content)) { + result = new GeneralResult<>(false, "参数为空!"); + } else { + try { + WorkerHost target = JSONObject.parseObject(content, WorkerHost.class); + result = new GeneralResult(true, target, "success"); + } catch (Exception e) { + result = new GeneralResult(false, e.getLocalizedMessage()); + } + } + return result; + } + + public static List parseTargets(String content) throws NodeFormatException { + if (StringUtils.isEmpty(content)) { + throw new NodeFormatException("参数为空!"); + } else { + try { + List targets = JSONArray.parseArray(content, WorkerHost.class); + return targets; + } catch (Exception e) { + throw new NodeFormatException("目标机器参数类型错误!", e); + } + } + } + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPasd() { + return pasd; + } + + public void setPasd(String pasd) { + this.pasd = pasd; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + /** + * @return the rawName + */ + public String getRawName() { + return rawName; + } + + /** + * @param rawName the rawName to set + */ + public void setRawName(String rawName) { + this.rawName = rawName; + } + + public String getTask() { + return task; + } + + public void setTask(String task) { + this.task = task; + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getSequenceId() { + return sequenceId; + } + + public void setSequenceId(String sequenceId) { + this.sequenceId = sequenceId; + } + + public String getPkey() { + return pkey; + } + + public void setPkey(String pkey) { + this.pkey = pkey; + } + + public Boolean getSudo() { + return sudo; + } + + public void setSudo(Boolean sudo) { + this.sudo = sudo; + } + + public Long getSegmentId() { + return segmentId; + } + + public void setSegmentId(Long segmentId) { + this.segmentId = segmentId; + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerScript.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerScript.java new file mode 100644 index 0000000..3927d1b --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/WorkerScript.java @@ -0,0 +1,109 @@ +package com.bocloud.ams.task.model; + +/** + * Worker执行的脚本内容封装类 + * + * @author dmw + */ +public class WorkerScript { + + /** + * 脚本类型 + */ + private String type; + /** + * 脚本参数 + */ + private String params; + /** + * 脚本内容 + */ + private String content; + /** + * 执行脚本时候的可选参数 + */ + private Option options; + + public WorkerScript(String type, String params, String content) { + super(); + this.type = type; + this.params = params; + this.content = content; + } + + public WorkerScript(String type, String params, String content, Option options) { + super(); + this.type = type; + this.params = params; + this.content = content; + this.options = options; + } + + /** + * @return the options + */ + public Option getOptions() { + return options; + } + + /** + * @param options the options to set + */ + public void setOptions(Option options) { + this.options = options; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the params + */ + public String getParams() { + return params; + } + + /** + * @param params the params to set + */ + public void setParams(String params) { + this.params = params; + } + + /** + * @return the content + */ + public String getContent() { + return content; + } + + /** + * @param content the content to set + */ + public void setContent(String content) { + this.content = content; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "WorkerScript [type=" + type + ", params=" + params + ", content=" + content + ", options=" + options + + "]"; + } + +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/enums/TaskParam.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/enums/TaskParam.java new file mode 100644 index 0000000..4a146fd --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/model/enums/TaskParam.java @@ -0,0 +1,74 @@ +package com.bocloud.ams.task.model.enums; + +import com.megatron.common.model.GeneralResult; +import org.apache.commons.lang3.StringUtils; + +/** + * 任务参数 + * + * @author dmw + */ +public enum TaskParam { + + /** + * 任务类型:resource,maintain,software,scheduled + */ + TASKTYPE, + /** + * 上级任务,主要用来记录定时任务的ID + */ + TASKPJOB, + /** + * 任务数据 + */ + TASKDATA, + /** + * 任务编码 + */ + TASKCODE, + /** + * 超时时间 + */ + TIMEOUT, + /** + * + */ + TARGETS, + /** + * + */ + RECORDID, + /** + * + */ + USERID, + /** + * + */ + PUREREAL, + /** + * + */ + INSTANCEID, + /** + * + */ + RETRYTIMES, + /** + * 任务队列 + */ + QUEUE; + + public static GeneralResult hasValue(String value) { + if (StringUtils.isEmpty(value)) { + return new GeneralResult<>(false, "参数为空!"); + } + TaskParam[] params = TaskParam.values(); + for (TaskParam param : params) { + if (param.name().equalsIgnoreCase(value)) { + return new GeneralResult(true, param, "success"); + } + } + return new GeneralResult<>(false, "数值不存在!"); + } +} diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBDriver.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBDriver.java new file mode 100644 index 0000000..6167f03 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBDriver.java @@ -0,0 +1,45 @@ +package com.bocloud.ams.task.utils; + +import com.megatron.common.model.GeneralResult; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 20:57 2019/1/7 @ Modified By: + */ +public enum DBDriver { + /** + * Oracle数据库驱动 + */ + ORACLE("oracle.jdbc.OracleDriver"), + /** + * Mysql数据库驱动 + */ + MYSQL("com.mysql.jdbc.Driver"), + /** + * SQLServer数据库驱动 + */ + SQLSERVER_JTS("net.sourceforge.jtds.jdbc.Driver"), + /** + * SQLServer数据库驱动 + */ + SQLSERVER_MS("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + + private String driver; + + DBDriver(String driver) { + this.driver = driver; + } + + public String getDriver() { + return driver; + } + + public static GeneralResult has(String driver) { + for (DBDriver dbDriver : DBDriver.values()) { + if (dbDriver.name().equalsIgnoreCase(driver)) { + return new GeneralResult(true, dbDriver, "success"); + } + } + return new GeneralResult<>(true, "not found!"); + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBTool.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBTool.java new file mode 100644 index 0000000..e85b057 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/DBTool.java @@ -0,0 +1,84 @@ +package com.bocloud.ams.task.utils; + +/** + * @ Description: + * @ Author :丁明威 + * @ Date :Created in 19:20 2019/1/2 + * @ Modified By: + */ +public class DBTool { + /** + * 获取mysql的分页语句 pageNo 从0 开始 + * + * @param sql + * @param pageNo + * @param pageSize + * @return + */ + public static String buildMysqlPageSql(String sql, Integer pageNo, Integer pageSize) { + StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); + sqlBuilder.append(sql); + if (pageNo == 0) { + sqlBuilder.append(" LIMIT ").append(pageSize); + } else { + sqlBuilder.append(" LIMIT ").append(pageNo).append(",").append(pageSize); + } + return sqlBuilder.toString(); + } + + /** + * 获取oracle的分页语句 pageNo 从0 开始 + * + * @param sql + * @param pageNo + * @param pageSize + * @return + */ + public static String buildOraclePageSql(String sql, Integer pageNo, Integer pageSize) { + int startRow = pageNo; + int endRow = pageNo + pageSize; + StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120); + if (startRow > 0) { + sqlBuilder.append("SELECT * FROM ( "); + } + if (endRow > 0) { + sqlBuilder.append(" SELECT TMP_PAGE.*, ROWNUM ROW_ID FROM ( "); + } + sqlBuilder.append(sql); + if (endRow > 0) { + sqlBuilder.append(" ) TMP_PAGE WHERE ROWNUM <= ").append(endRow); + } + if (startRow > 0) { + sqlBuilder.append(" ) WHERE ROW_ID > ").append(startRow); + } + return sqlBuilder.toString(); + } + + /** + * 获取sqlserver2012的分页语句 pageNo 由 0 开始 + * + * @param sql + * @param pageNo + * @param pageSize + * @return + */ + public static String buildSqlServer2012PageSql(String sql, Integer pageNo, Integer pageSize) { + StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); + sqlBuilder.append(sql).append(" OFFSET ").append(pageNo).append(" ROWS ").append(" FETCH NEXT ") + .append(pageSize).append(" ROWS ONLY"); + return sqlBuilder.toString(); + } + + public static boolean isSqlServer(String driver) { + return DBDriver.SQLSERVER_JTS.getDriver().equals(driver) || DBDriver.SQLSERVER_MS.getDriver().equals(driver); + } + + public static boolean isOracle(String driver) { + return DBDriver.ORACLE.getDriver().equals(driver); + } + + public static boolean isMySql(String driver) { + return DBDriver.MYSQL.getDriver().equals(driver); + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/ParamBuilder.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/ParamBuilder.java new file mode 100644 index 0000000..f864033 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/utils/ParamBuilder.java @@ -0,0 +1,39 @@ +package com.bocloud.ams.task.utils; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.worker.InputClassLocator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ParamBuilder { + + private InputClassLocator locator; + + /** + * 默认构造方法 + */ + public ParamBuilder() { + this.locator = new InputClassLocator(); + } + + /** + * 参数构建 + * + * @param code + * 任务节点模型 例如:task.resource.cvm.osp + * @param data + * 任务节点数据 + * @return 任务节点执行器的执行任务参数 + */ + public Object buildParam(String code, String data) { + Class clazz = locator.getInputClass(code); + try { + return JSONObject.parseObject(data, clazz); + } catch (Exception e) { + log.error("transfer task param of code {} error!", code, e); + } + return null; + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/AbstractWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/AbstractWorker.java new file mode 100644 index 0000000..be436c1 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/AbstractWorker.java @@ -0,0 +1,76 @@ +package com.bocloud.ams.task.worker; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.megatron.common.model.GeneralResult; + +import com.megatron.common.model.Result; +import com.megatron.framework.http.core.ServiceFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitAdmin; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 14:49 2018/12/27 @ Modified + * By: + */ +@Slf4j +public abstract class AbstractWorker { + String code; + RabbitAdmin rabbitAdmin; + ServiceFactory serviceFactory; + private Integer timeout = Integer.valueOf(10 * 60); + + public AbstractWorker(String code, RabbitAdmin rabbitAdmin, ServiceFactory serviceFactory, Integer timeout) { + this.code = code; + if (null != timeout && timeout > 0) { + this.timeout = timeout; + } + this.rabbitAdmin = rabbitAdmin; + this.serviceFactory = serviceFactory; + } + + public GeneralResult execute(Object param) { + GeneralResult result = null; + try { + init(param); + result = call(); + } catch (NodeFormatException e) { + log.error("worker param illegal!", e); + result = GeneralResult.FAILED("worker param illegal!!"); + } + return result; + } + + protected abstract void init(Object param) throws NodeFormatException; + + protected abstract GeneralResult call(); + + public Result buildResult(GeneralResult result) { + String message = JSONObject.toJSONString(result); + return new Result(result.isSuccess(), message); + } + + public Integer getTimeout() { + return timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + + public RabbitAdmin getRabbitAdmin() { + return rabbitAdmin; + } + + public ServiceFactory getServiceFactory() { + return serviceFactory; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/DatabaseWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/DatabaseWorker.java new file mode 100644 index 0000000..0592bba --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/DatabaseWorker.java @@ -0,0 +1,426 @@ +package com.bocloud.ams.task.worker; + +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.annotation.Worker; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.input.DBInput; +import com.bocloud.ams.task.model.DBFront; +import com.bocloud.ams.task.utils.DBDriver; +import com.bocloud.ams.task.utils.DBTool; +import com.megatron.common.encrypt.AESEncryptor; +import com.megatron.common.encrypt.Encryptor; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Result; +import com.megatron.framework.http.core.ServiceFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.util.StringUtils; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 18:05 2018/12/28 @ Modified + * By: + */ +@Slf4j +@Worker(name = "task.maintain.database") +public class DatabaseWorker extends AbstractWorker { + /** + * 超时时间,默认超时时间为10分钟 + */ + private Integer timeout = 1000 * 60 * 10; + /** + * 数据库连接字符串 + */ + private String url; + /** + * 数据库操作参数 + */ + private DBFront param; + + /** + * 数据库连接 + */ + private Connection connection; + + public DatabaseWorker(String code, RabbitAdmin rabbitAdmin, ServiceFactory serviceFactory, Integer timeout) { + super(code, rabbitAdmin, serviceFactory, timeout); + } + + @Override + public void init(Object param) throws NodeFormatException { + if (param instanceof DBInput) { + DBInput input = (DBInput) param; + this.param = input.getFronts(); + this.url = buildConnectionUrl(this.param.getJdbcUrl()); + } else { + throw new NodeFormatException("database task params illegel!"); + } + } + + @Override + public GeneralResult call() { + GeneralResult result; + if (loadDriver().isFailed()) { + log.error("database driver [{}] load exception ! ", param.getDriver()); + result = buildErrorResult("无法加载到驱动,驱动参数为" + param.getDriver()); + } else { + try { + List scriptList = splitScript(param.getContent()); + List scriptResult = new ArrayList<>(); + ExecutorService executor = Executors.newSingleThreadExecutor(); + // 开启一个子线程执行sql任务,当前线程进行超时等待 + Future> future = getNodeResultFuture(scriptList, scriptResult, executor); + // 处理future的结果 + result = getNodeResult(future, executor); + } catch (Exception e) { + log.error("database executor exception:", e); + result = buildErrorResult("无法加载到驱动,驱动参数为" + param.getDriver()); + } + } + return result; + } + + private GeneralResult getNodeResult(Future> future, ExecutorService executor) { + ExecutorService timeoutExecutor = Executors.newSingleThreadExecutor(); + try { + // 超时时间+10秒之后,查看结果,如果没有结果,数据库任务可能已经超时 + return future.get(Long.valueOf(timeout) + 10000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.error("线程异常", e); + return buildErrorResult("出现异常错误"); + } catch (ExecutionException e) { + log.error("执行task错误", e); + return buildErrorResult("执行task错误"); + } catch (TimeoutException e) { + // 超时 + future.cancel(true); + try { + // 尝试终止连接 + connection.abort(timeoutExecutor); + return buildErrorResult("taks已经取消,请等待数据回滚"); + } catch (SQLException e1) { + log.error("终端连接失败", e1); + } + try { + // 如果终止连接失败,可能是jdbc驱动没有实现终止的方法,此时只能阻塞,然后等待操作完回滚了 + connection.rollback(); + } catch (SQLException e1) { + log.error("超时回滚出错", e); + return buildErrorResult("执行sql失败!"); + } + return buildErrorResult("taks超时取消"); + } finally { + closeConnection(); + executor.shutdown(); + timeoutExecutor.shutdown(); + } + } + + /** + * 执行业务方法 + * + * @param scriptList + * @param scriptResult + * @param executor + * @return + */ + private Future> getNodeResultFuture(List scriptList, List scriptResult, + ExecutorService executor) { + return executor.submit(new Callable>() { + @Override + public GeneralResult call() throws Exception { + if (scriptList.isEmpty()) { + log.error("database sctipt is empty!"); + return buildErrorResult("script脚本有误"); + } + PreparedStatement pstmt = null; + boolean haveUpdateOp = false; + try { + // 密码解密 + Encryptor encryptor = new AESEncryptor(); + String password = encryptor.decrypt(param.getPassword().trim(), null); + // 开启连接 + connection = DriverManager.getConnection(url, param.getUsername(), + password); + } catch (SQLException se) { + log.error("build database connection error!", se); + return buildErrorResult("无法建立连接,url参数为" + url); + } + try { + // 设置自动提交关闭 + connection.setAutoCommit(false); + for (String toExecute : scriptList) { + pstmt = connection.prepareStatement(toExecute); + pstmt.setQueryTimeout(timeout); + // oracle使用此配置有效,mysql无效 + JSONArray resultStr = null; + if (isSelect(toExecute) || isShow(toExecute)) { + ResultSet resultSet = pstmt.executeQuery(); + resultStr = JSONArray.parseArray(resultSetToJson(resultSet)); + } else { + haveUpdateOp = true; + int updateCount = pstmt.executeUpdate(); + resultStr = new JSONArray(); + JSONObject object = new JSONObject(); + object.put("result", "受影响的行数为" + updateCount); + resultStr.add(object); + } + scriptResult.add(resultStr); + closePrepareStatement(pstmt); + } + connection.commit(); + } catch (Exception e) { + log.error("执行sql失败!", e); + try { + if (haveUpdateOp) { + connection.rollback(); + } + } catch (Exception e1) { + log.error("尝试数据库回滚失败", e1); + return buildErrorResult("调用数据回滚失败"); + } + return buildErrorResult(e.getMessage()); + } finally { + closePrepareStatement(pstmt); + closeConnection(); + } + return buildSuccessResult("script执行成功", scriptResult); + } + }); + } + + /** + * 关闭数据库连接 + */ + private void closeConnection() { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + log.error("连接关闭失败", e); + } + } + } + + /** + * 关闭preparedstatement + * + * @param pstmt + */ + private void closePrepareStatement(PreparedStatement pstmt) { + if (pstmt != null) { + try { + pstmt.close(); + } catch (SQLException e) { + log.error("pstmt关闭失败", e); + } + } + } + + /** + * 创建错误结果 + * + * @param message + * @return + */ + private GeneralResult buildErrorResult(String message) { + return new GeneralResult<>(false, message, "failed"); + } + + /** + * 创建成功结果 + * + * @param message + * @param results + * @return + */ + private GeneralResult buildSuccessResult(String message, List results) { + return new GeneralResult<>(true, results, message); + } + + /** + * 生成数据库连接串 + * + * @return + */ + private String buildConnectionUrl(String url) throws NodeFormatException { // 此方法可能会用 + String prefix = ""; + try { + switch (DBDriver.valueOf(param.getDatabase().toUpperCase())) { + case MYSQL: + prefix = "jdbc:mysql://"; + break; + case ORACLE: + prefix = "jdbc:oracle:thin:@"; + break; + case SQLSERVER_MS: + prefix = "jdbc:sqlserver://"; + break; + case SQLSERVER_JTS: + prefix = "jdbc:jtds:sqlserver://"; + break; + default: + break; + } + if (!StringUtils.hasText(prefix)) { + log.error("jdbc url is illegel!"); + throw new NodeFormatException("数据库操作参数错误!"); + } + } catch (Exception e) { + log.error("jdbc url is illegel!", e); + throw new NodeFormatException("数据库操作参数错误!"); + } + return prefix + url; + } + + /** + * 判断是否查询操作 + * + * @param script + * @return + */ + private boolean isSelect(String script) { + return script.toLowerCase().trim().startsWith("select"); + } + + /** + * 判断是否查询操作 + * + * @param script + * @return + */ + private boolean isShow(String script) { + return script.toLowerCase().trim().startsWith("show"); + } + + /** + * ResultSet转Json + * + * @param rs + * @return + * @throws SQLException + */ + public String resultSetToJson(ResultSet rs) throws SQLException { + // json数组 + JSONArray array = new JSONArray(); + // 获取列数 + ResultSetMetaData metaData = rs.getMetaData(); + int columnCount = metaData.getColumnCount(); + // 遍历ResultSet中的每条数据 + while (rs.next()) { + JSONObject jsonObj = new JSONObject(); + // 遍历每一列 + for (int i = 1; i <= columnCount; i++) { + String columnName = metaData.getColumnLabel(i); + String value = rs.getString(columnName); + jsonObj.put(columnName, value); + } + array.add(jsonObj); + } + return array.toJSONString(); + } + + /** + * 对脚本进行分析拆分 + * + * @param script + * @return + */ + private List splitScript(String script) throws Exception { + List retList = new ArrayList<>(); + String driver = param.getDBDriver().getDriver(); + DbType dbType = null; + if (DBTool.isMySql(driver)) { + dbType = JdbcConstants.MYSQL; + } else if (DBTool.isOracle(driver)) { + dbType = JdbcConstants.ORACLE; + } else if (DBTool.isSqlServer(driver)) { + dbType = JdbcConstants.SQL_SERVER; + } + // 格式化输出 + List stmtList = SQLUtils.parseStatements(script, dbType); + // 遍历解析出的sql语句 + for (int i = 0; i < stmtList.size(); i++) { + SQLStatement stmt = stmtList.get(i); + String sql = stmt.toString(); + if (StringUtils.hasText(sql)) { + if (isSelect(sql)) { + // 查询操作的话加上分页 + sql = sql.replaceAll("([;| ]+)$", " "); +// if (DBTool.isMySql(driver)) { +// sql = DBTool.buildMysqlPageSql(sql, 0, 10); +// } else if (DBTool.isOracle(driver)) { +// sql = DBTool.buildOraclePageSql(sql, 0, 10); +// } else if (DBTool.isSqlServer(driver)) { +// // 暂时只支持sqlserver2012 +// sql = DBTool.buildSqlServer2012PageSql(sql, 0, 10); +// } + } + retList.add(sql); + } + } + return retList; + } + + private Result loadDriver() { + try { + // 加载MySql的驱动类 + Class.forName(param.getDBDriver().getDriver()); + } catch (ClassNotFoundException e) { + log.error("找不到驱动程序类 ,加载驱动失败!", e); + return new Result(false, "找不到驱动程序类 ,加载驱动失败!"); + } catch (Exception e) { + log.error("get driver exception {}!", e.getMessage()); + return new Result(false, "找不到驱动程序类 ,加载驱动失败!"); + } + return new Result(true, "load success!"); + } + + /** + * @return the url + */ + public String getUrl() { + return url; + } + + /** + * @param url the url to set + */ + public void setUrl(String url) throws NodeFormatException { + buildConnectionUrl(url); + } + + public DBFront getParam() { + return param; + } + + public void setParam(DBFront param) { + this.param = param; + } + + /** + * @return the timeout + */ + @Override + public Integer getTimeout() { + return timeout; + } + + /** + * @param timeout the timeout to set + */ + @Override + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/InputClassLocator.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/InputClassLocator.java new file mode 100644 index 0000000..ca6afa7 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/InputClassLocator.java @@ -0,0 +1,51 @@ +package com.bocloud.ams.task.worker; + +import com.bocloud.ams.task.annotation.Module; +import com.bocloud.ams.task.input.Input; +import com.megatron.common.locator.ClassLocator; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @ Description:前端输入类定位器,用来对Input的具体实现类基于code进行定位, @ Author :丁明威 @ Date + * :Created in 16:49 2018/12/27 @ Modified By: + */ +@Slf4j +public class InputClassLocator { + private static Map> inputClassMap = new ConcurrentHashMap<>(); + + private List> getInputClasses(String code) { + @SuppressWarnings("rawtypes") + List> allClass = ClassLocator.getAllClass(Input.class.getPackage().getName(), "input"); + List> fixClass = new ArrayList<>(); + for (Class clazz : allClass) { + if (clazz.isAnnotationPresent(Module.class)) { + Module module = (Module) clazz.getAnnotation(Module.class); + if (module.code().equalsIgnoreCase(code)) { + fixClass.add(clazz); + } + } + } + return fixClass; + } + + public Class getInputClass(String code) { + if (inputClassMap.containsKey(code)) { + return inputClassMap.get(code); + } + List> inputClassList = getInputClasses(code); + if (inputClassList.isEmpty()) { + return null; + } + if (inputClassList.size() > 1) { + log.error("more than one class found!"); + return null; + } + inputClassMap.put(code, inputClassList.get(0)); + return inputClassList.get(0); + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MaintainWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MaintainWorker.java new file mode 100644 index 0000000..20fe68c --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MaintainWorker.java @@ -0,0 +1,144 @@ +package com.bocloud.ams.task.worker; + +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.executor.WorkerDispatcher; +import com.bocloud.ams.task.input.Target; +import com.bocloud.ams.task.model.TargetGroup; +import com.bocloud.ams.task.model.WorkerHost; +import com.megatron.common.encrypt.AESEncryptor; +import com.megatron.common.encrypt.Encryptor; +import com.megatron.common.enums.OSCategory; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.utils.ListTool; +import com.megatron.framework.http.core.ServiceFactory; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitAdmin; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 14:52 2018/12/27 @ Modified + * By: + */ +@Slf4j +public abstract class MaintainWorker extends AbstractWorker { + /** + * 目标主机数量经验值 + */ + int expNum = 100; + WorkerDispatcher dispatcher; + List> targets; + List> paramList; + + public MaintainWorker(String code, RabbitAdmin rabbitAdmin, ServiceFactory serviceFactory, Integer timeout) { + super(code, rabbitAdmin, serviceFactory, timeout); + this.targets = new ArrayList<>(); + this.dispatcher = new WorkerDispatcher(serviceFactory, rabbitAdmin); + paramList = Lists.newArrayList(); + } + + abstract void buildParam() throws NodeFormatException; + + @Override + protected GeneralResult call() { + GeneralResult result; + try { + // 任务分发并获取整体结果 + result = dispatcher.execute(paramList, getTimeout()); + } catch (NodeFormatException e) { + result = GeneralResult.FAILED(e.getMessage()); + } + if (log.isDebugEnabled()) { + log.debug("task result is {}", result); + } + return result; + } + + /** + * 主机分片 + * + * @param target + */ + public void burst(Target target) throws NodeFormatException { + GeneralResult targetGroupResult = groupTarget(target.getData()); + if (targetGroupResult.isSuccess()) { + TargetGroup targetGroup = targetGroupResult.getData(); + this.targets.addAll(splitTarget(targetGroup.getLinuxs())); + this.targets.addAll(splitTarget(targetGroup.getWindows())); + } + } + + /** + * 将目标机器按照操作系统类型分为Windows和Linux两组 + * + * @param targets + * @return + */ + private GeneralResult groupTarget(List targets) throws NodeFormatException { + List linuxs = Lists.newArrayList(); + List windows = Lists.newArrayList(); + if (ListTool.isEmpty(targets)) { + throw new NodeFormatException("目标机器为空!"); + } + for (WorkerHost target : targets) { + if (OSCategory.LINUX.name().equalsIgnoreCase(target.getCategory())) { + linuxs.add(target); + } else if (OSCategory.WINDOWS.name().equalsIgnoreCase(target.getCategory())) { + windows.add(target); + } else { + log.error("未知操作系统,放置到Linux操作系统中"); + linuxs.add(target); + } + } + return new GeneralResult(true, new TargetGroup(windows, linuxs), "success"); + } + + /** + * 根据每个worker处理目标机器数的经验值划分每个worker处理的目标机器IP列表 + * + * @param targets + * @return + */ + private List> splitTarget(List targets) { + List> targetList = new ArrayList<>(16); + int step; + if (this.getCode().equalsIgnoreCase("task.maintain.recovery")) { + step = 1; + } else { + step = expNum; + } + for (int i = 0; i < targets.size(); i = i + step) { + List targetArray = new ArrayList<>(16); + for (int j = i; j < i + step && j < targets.size(); j++) { + WorkerHost workerHost = targets.get(j); + workerHost.setPasd(workerHost.getPasd()); + targetArray.add(workerHost); + } + targetList.add(targetArray); + } + return targetList; + } + + public static void main(String[] args) { + AESEncryptor aesEncryptor = new AESEncryptor(); + System.out.println(aesEncryptor.decrypt("NVN3gZaJ1DETbj/TCezSU8orgmZbJOtpn0nR7vHL86I=", null)); + System.out.println(aesEncryptor.encrypt("sa@123", null)); + Encryptor encryptor = new AESEncryptor(); + System.out.println(encryptor.decrypt("NDVfYMofbBCFj/5abVN4xA==", null)); + } + + public int getExpNum() { + return expNum; + } + + public void setExpNum(int expNum) { + this.expNum = expNum; + } + + public List> getTargets() { + return targets; + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MethodWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MethodWorker.java new file mode 100644 index 0000000..485295c --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/MethodWorker.java @@ -0,0 +1,118 @@ +package com.bocloud.ams.task.worker; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.annotation.Worker; +import com.bocloud.ams.task.input.HttpInput; +import com.bocloud.ams.task.model.HttpFront; +import com.megatron.common.enums.HttpRequestMethod; +import com.megatron.common.enums.PostDataFormat; +import com.megatron.common.http.HttpClient; +import com.megatron.common.model.GeneralResult; +import com.megatron.common.model.Result; +import com.megatron.framework.http.core.ServiceFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * @ Description:Http接口调用worker执行器 @ Author :丁明威 @ Date :Created in 14:54 + * 2018/12/27 @ Modified By: + */ +@Worker(name = "task.maintain.method") +public class MethodWorker extends AbstractWorker { + /** + * 请求URL + */ + private String url; + /** + * 超时时间,默认超时1分钟 + */ + private int timeout = 60 * 1000; + /** + * 请求方法 + */ + private HttpRequestMethod method; + /** + * 请求参数数据格式 + */ + private PostDataFormat postDataFormat; + + private Map header; + private Map params; + + private HttpInput input; + + public MethodWorker(String code, RabbitAdmin rabbitAdmin, ServiceFactory serviceFactory, Integer timeout) { + super(code, rabbitAdmin, serviceFactory, timeout); + this.postDataFormat = PostDataFormat.FORM_DATA; + if (null != timeout && timeout > 0) { + this.timeout = timeout * 1000; + } + } + + @Override + protected GeneralResult call() { + Result result; + HttpClient httpClient = new HttpClient(timeout, postDataFormat); + if (null != postDataFormat){ + switch (postDataFormat) { + case RAW: + covertParam(); + break; + case BINARY: + covertParam(); + break; + default: + break; + } + } + switch (method) { + case GET: + result = httpClient.get(header, params, url); + break; + case POST: + result = httpClient.post(header, params, url); + break; + case PATCH: + result = httpClient.patch(header, params, url); + break; + case PUT: + result = httpClient.patch(header, params, url); + break; + case DELETE: + result = httpClient.delete(header, params, url); + break; + case TRACE: + result = httpClient.trace(header, params, url); + break; + default: + // 默认采用get请求 + result = httpClient.get(header, params, url); + break; + } + return new GeneralResult<>(result.isSuccess(), JSONObject.parseObject(result.getMessage()), "success"); + } + + @Override + protected void init(Object param) { + if (param instanceof HttpInput) { + this.input = (HttpInput) param; + HttpFront front = input.getFronts(); + this.url = front.getUrl(); + this.method = front.getMethod(); + this.params = front.getParams(); + this.header = front.getHeaders(); + this.postDataFormat = front.getFormat(); + } + } + + private void covertParam() { + if (StringUtils.hasText(this.input.getFronts().getBody())) { + @SuppressWarnings("unchecked") + Map body = JSONObject.parseObject(this.input.getFronts().getBody(), HashMap.class); + params.putAll(body); + } + } +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/ScriptWorker.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/ScriptWorker.java new file mode 100644 index 0000000..2eaf736 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/ScriptWorker.java @@ -0,0 +1,95 @@ +package com.bocloud.ams.task.worker; + +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.rabbit.core.RabbitAdmin; + +import com.alibaba.fastjson.JSONObject; +import com.bocloud.ams.task.annotation.Worker; +import com.bocloud.ams.task.exception.NodeFormatException; +import com.bocloud.ams.task.input.ScriptInput; +import com.bocloud.ams.task.input.Target; +import com.bocloud.ams.task.model.Option; +import com.bocloud.ams.task.model.ScriptFront; +import com.bocloud.ams.task.model.WorkerHost; +import com.bocloud.ams.task.model.WorkerScript; +import com.megatron.common.utils.ListTool; +import com.megatron.common.utils.MapTools; +import com.megatron.framework.http.core.ServiceFactory; + +import lombok.extern.slf4j.Slf4j; + +/** + * @ Description: @ Author :丁明威 @ Date :Created in 17:46 2019/1/4 @ Modified By: + */ +@Slf4j +@Worker(name = "task.maintain.script") +public class ScriptWorker extends MaintainWorker { + private ScriptInput input; + + /** + * 构造方法 + * + * @param code + * @param rabbitAdmin + * @param serviceFactory + * @param timeout + */ + public ScriptWorker(String code, RabbitAdmin rabbitAdmin, ServiceFactory serviceFactory, Integer timeout) { + super(code, rabbitAdmin, serviceFactory, timeout); + } + + @Override + protected void init(Object param) throws NodeFormatException { + if (param instanceof ScriptInput) { + this.input = (ScriptInput)param; + Target target = input.getTarget(); + // 目标主机切片 + burst(target); + // 构建请求参数 + buildParam(); + } else { + log.error("Script worker param illegal!"); + throw new NodeFormatException("Worker Param illegal!"); + } + } + + /** + * 参数构建 + */ + @Override + void buildParam() { + if (null == input) { + return; + } + ScriptFront front = input.getFronts(); + String content = front.getContent(); + if (!StringUtils.isEmpty(front.getParams())) { + List params = JSONObject.parseArray(front.getParams(), JSONObject.class); + if (!ListTool.isEmpty(params)) { + for (JSONObject param : params) { + content = content.replaceAll("\\$\\{\\{" + param.getString("key") + "\\}\\}", + Matcher.quoteReplacement(param.getString("value"))); + } + } + } + Target target = input.getTarget(); + if (null == target.getSudo()) { + target.setSudo(false); + } + Option options = new Option(null, target.getSudo(), target.getBecomeUser(), target.getBecomePass(), + target.getBecomeMethod()); + WorkerScript script = new WorkerScript(front.getCategory(), null, content, options); + for (List hosts : this.targets) { + Map param = MapTools.simpleMap("targets", hosts); + param.put("script", script); + param.put("response", "async"); + param.put("timeout", this.getTimeout()); + paramList.add(param); + } + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerClassLocator.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerClassLocator.java new file mode 100644 index 0000000..e3ec0e3 --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerClassLocator.java @@ -0,0 +1,51 @@ +package com.bocloud.ams.task.worker; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.bocloud.ams.task.annotation.Worker; +import com.megatron.common.locator.ClassLocator; + +import lombok.extern.slf4j.Slf4j; + +/** + * Worker类定位器 + */ +@Slf4j +public class WorkerClassLocator { + private static Map> workerClassMap = new ConcurrentHashMap<>(); + + public List> getWorkerClasses(String code) { + @SuppressWarnings("rawtypes") + List> allClass = ClassLocator.getAllClass(AbstractWorker.class.getPackage().getName(), "worker"); + List> fixClass = new ArrayList<>(); + for (Class clazz : allClass) { + if (clazz.isAnnotationPresent(Worker.class)) { + Worker worker = (Worker)clazz.getAnnotation(Worker.class); + if (worker.name().equalsIgnoreCase(code)) { + fixClass.add(clazz); + } + } + } + return fixClass; + } + + public Class getWorkerClass(String code) { + if (workerClassMap.containsKey(code)) { + return workerClassMap.get(code); + } + List> inputClassList = getWorkerClasses(code); + if (inputClassList.isEmpty()) { + return null; + } + if (inputClassList.size() > 1) { + log.error("more than one class found!"); + return null; + } + workerClassMap.put(code, inputClassList.get(0)); + return inputClassList.get(0); + } + +} \ No newline at end of file diff --git a/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerFactory.java b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerFactory.java new file mode 100644 index 0000000..efea00d --- /dev/null +++ b/bocloud.ams.task/src/main/java/com/bocloud/ams/task/worker/WorkerFactory.java @@ -0,0 +1,52 @@ +package com.bocloud.ams.task.worker; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import com.megatron.framework.http.core.ServiceFactory; +import com.megatron.framework.lock.LockFactory; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Repository +public class WorkerFactory { + private final ServiceFactory serviceFactory; + private final RabbitAdmin rabbitAdmin; + private WorkerClassLocator classLocator; + + @Autowired + public WorkerFactory(RabbitAdmin rabbitAdmin, StringRedisTemplate redisTemplate, ServiceFactory serviceFactory, + LockFactory lockFactory) { + this.rabbitAdmin = rabbitAdmin; + this.serviceFactory = serviceFactory; + classLocator = new WorkerClassLocator(); + } + + public AbstractWorker buildWorker(String code, Integer timeout) { + Class clazz = classLocator.getWorkerClass(code); + if (null != clazz) { + try { + Constructor constructor = + clazz.getDeclaredConstructor(String.class, RabbitAdmin.class, ServiceFactory.class, Integer.class); + try { + return (AbstractWorker)constructor.newInstance(code, rabbitAdmin, serviceFactory, timeout); + } catch (IllegalAccessException e) { + log.error("init worker {} of {} IllegalAccessException!", clazz, code, e); + } + } catch (NoSuchMethodException e) { + log.error("init worker {} of {} NoSuchMethodException!", clazz, code, e); + } catch (InstantiationException e) { + log.error("init worker {} of {} InstantiationException!", clazz, code, e); + } catch (InvocationTargetException e) { + log.error("init worker {} of {} InvocationTargetException!", clazz, code, e); + } + } + return null; + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9a8e6b9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,144 @@ + + + 4.0.0 + + + com.freedom + megatron + 3.0.0 + + com.bocloud + bocloud.ams + 6.5.0-LTS-SZ + pom + + bocloud.ams.booter + bocloud.ams.entity + bocloud.ams.service + bocloud.ams.repository + bocloud.ams.task + + + 6.5.0-LTS-SZ + 6.5.0-LTS + + + + + + com.freedom + megatron.common + ${megatron.version} + + + com.freedom + megatron.database + ${megatron.version} + + + com.freedom + megatron.framework + ${megatron.version} + + + com.freedom + megatron.microservice + ${megatron.version} + + + com.bocloud + bocloud.boot.common + ${bocloud.common.version} + + + com.bocloud + bocloud.ams.entity + ${bocloud.ams.version} + + + com.bocloud + bocloud.ams.repository + ${bocloud.ams.version} + + + com.bocloud + bocloud.ams.service + ${bocloud.ams.version} + + + com.bocloud + bocloud.ams.task + ${bocloud.ams.version} + + + org.apache.poi + poi + 3.16 + + + org.apache.poi + poi-ooxml + 3.16 + + + commons-fileupload + commons-fileupload + 1.3.3 + + + commons-io + commons-io + 2.5 + + + + + + bocloud-release + BoCloud Release + ${release.server.url} + + + bocloud-snapshot + BoCloud Snapshot + ${snapshot.server.url} + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.4.1 + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 21 + 21 + ${file_encoding} + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + 3.0.0-M3 + + + + \ No newline at end of file