content: package org.dbsyncer.manager;
  
  import org.dbsyncer.manager.event.ClosedEvent;
  import org.dbsyncer.parser.ProfileComponent;
  import org.dbsyncer.parser.enums.MetaEnum;
  import org.dbsyncer.parser.model.Mapping;
  import org.dbsyncer.parser.model.Meta;
  import org.springframework.context.ApplicationListener;
  import org.springframework.stereotype.Component;
  import org.springframework.util.Assert;
  
  import javax.annotation.Resource;
  import java.time.Instant;
  import java.util.Map;
  
  /**
   * @author AE86
   * @version 1.0.0
   * @date 2019/9/16 23:59
   */
  @Component
  public class ManagerFactory implements ApplicationListener<ClosedEvent> {
  
      @Resource
      private ProfileComponent profileComponent;
  
      @Resource
      private Map<String, Puller> map;
  
      @Override
      public void onApplicationEvent(ClosedEvent event) {
          changeMetaState(event.getMetaId(), MetaEnum.READY);
      }
  
      public void start(Mapping mapping) {
          Puller puller = getPuller(mapping);
  
          // 标记运行中
          changeMetaState(mapping.getMetaId(), MetaEnum.RUNNING);
  
          try {
              puller.start(mapping);
          } catch (Exception e) {
              // rollback
              changeMetaState(mapping.getMetaId(), MetaEnum.READY);
              throw new ManagerException(e.getMessage());
          }
      }
  
      public void close(Mapping mapping) {
          Puller puller = getPuller(mapping);
  
          // 标记停止中
          String metaId = mapping.getMetaId();
          changeMetaState(metaId, MetaEnum.STOPPING);
  
          puller.close(metaId);
      }
  
      public void changeMetaState(String metaId, MetaEnum metaEnum) {
          Meta meta = profileComponent.getMeta(metaId);
          int code = metaEnum.getCode();
          if (null != meta && meta.getState() != code) {
              meta.setState(code);
              meta.setUpdateTime(Instant.now().toEpochMilli());
              profileComponent.editConfigModel(meta);
          }
      }
  
      private Puller getPuller(Mapping mapping) {
          Assert.notNull(mapping, "驱动不能为空");
          String model = mapping.getModel();
          String metaId = mapping.getMetaId();
          Assert.hasText(model, "同步方式不能为空");
          Assert.hasText(metaId, "任务ID不能为空");
  
          Puller puller = map.get(model.concat("Puller"));
          Assert.notNull(puller, String.format("未知的同步方式: %s", model));
          return puller;
      }
  
  }