/** {@inheritDoc} */
  @Override
  public void deleteFarm(Long farmNo) {
    // 引数チェック
    if (farmNo == null) {
      throw new AutoApplicationException("ECOMMON-000003", "farmNo");
    }

    // ファームの存在チェック
    Farm farm = farmDao.read(farmNo);
    if (farm == null) {
      // ファームが存在しない場合
      return;
    }

    // コンポーネントが停止しているかどうかのチェック
    List<Component> components = componentDao.readByFarmNo(farmNo);
    for (Component component : components) {
      // ロードバランサのコンポーネントはチェックしない
      if (BooleanUtils.isTrue(component.getLoadBalancer())) {
        continue;
      }

      List<ComponentInstance> componentInstances =
          componentInstanceDao.readByComponentNo(component.getComponentNo());
      for (ComponentInstance componentInstance : componentInstances) {
        ComponentInstanceStatus status =
            ComponentInstanceStatus.fromStatus(componentInstance.getStatus());
        if (status != ComponentInstanceStatus.STOPPED) {
          // コンポーネントが停止状態でない場合
          throw new AutoApplicationException("ESERVICE-000202", component.getComponentName());
        }
      }
    }

    // インスタンスが停止しているかどうかのチェック
    List<Instance> instances = instanceDao.readByFarmNo(farmNo);
    for (Instance instance : instances) {
      // ロードバランサのインスタンスはチェックしない
      if (BooleanUtils.isTrue(instance.getLoadBalancer())) {
        continue;
      }

      if (InstanceStatus.fromStatus(instance.getStatus()) != InstanceStatus.STOPPED) {
        // インスタンスが停止状態でない場合
        throw new AutoApplicationException("ESERVICE-000203", instance.getInstanceName());
      }
    }

    // ロードバランサが停止しているかどうかのチェック
    List<LoadBalancer> loadBalancers = loadBalancerDao.readByFarmNo(farmNo);
    for (LoadBalancer loadBalancer : loadBalancers) {
      if (LoadBalancerStatus.fromStatus(loadBalancer.getStatus()) != LoadBalancerStatus.STOPPED) {
        // ロードバランサが停止状態でない場合
        throw new AutoApplicationException("ESERVICE-000207", loadBalancer.getLoadBalancerName());
      }
    }

    // ホストグループの削除処理
    Boolean useZabbix = BooleanUtils.toBooleanObject(Config.getProperty("zabbix.useZabbix"));
    if (BooleanUtils.isTrue(useZabbix)) {
      zabbixHostProcess.deleteFarmHostgroup(farmNo);
    }

    // ロードバランサの削除処理
    for (LoadBalancer loadBalancer : loadBalancers) {
      loadBalancerService.deleteLoadBalancer(loadBalancer.getLoadBalancerNo());
    }

    // コンポーネントの削除処理
    for (Component component : components) {
      componentService.deleteComponent(component.getComponentNo());
    }

    // インスタンスの削除処理
    for (Instance instance : instances) {
      instanceService.deleteInstance(instance.getInstanceNo());
    }

    // AWS関連の削除処理
    // AWSボリュームの削除処理
    // TODO: ボリューム自体の削除処理を別で行うようにする
    List<AwsVolume> awsVolumes = awsVolumeDao.readByFarmNo(farmNo);
    for (AwsVolume awsVolume : awsVolumes) {
      if (StringUtils.isEmpty(awsVolume.getVolumeId())) {
        continue;
      }

      IaasGatewayWrapper gateway =
          iaasGatewayFactory.createIaasGateway(farm.getUserNo(), awsVolume.getPlatformNo());
      try {
        // ボリュームの削除
        gateway.deleteVolume(awsVolume.getVolumeId());

        // EC2ではDeleteVolumeに時間がかかるため、Waitしない
        // awsProcessClient.waitDeleteVolume(volumeId);
      } catch (AutoException ignore) {
        // ボリュームが存在しない場合などに備えて例外を握りつぶす
      }
    }
    awsVolumeDao.deleteByFarmNo(farmNo);

    // VMware関連の削除処理
    // VLANの割り当てを解除
    List<VmwareNetwork> vmwareNetworks = vmwareNetworkDao.readByFarmNo(farmNo);
    for (VmwareNetwork vmwareNetwork : vmwareNetworks) {
      // PortGroupを削除
      VmwareProcessClient vmwareProcessClient =
          vmwareProcessClientFactory.createVmwareProcessClient(vmwareNetwork.getPlatformNo());
      try {
        vmwareNetworkProcess.removeNetwork(vmwareProcessClient, vmwareNetwork.getNetworkNo());
      } finally {
        vmwareProcessClient.getVmwareClient().logout();
      }

      // VLAN割り当てを解除
      vmwareNetwork.setFarmNo(null);
      vmwareNetworkDao.update(vmwareNetwork);
    }

    // ユーザ権限の削除
    userAuthDao.deleteByFarmNo(farmNo);

    // ファームの削除処理
    farmDao.deleteByFarmNo(farmNo);

    // イベントログ出力
    eventLogger.log(
        EventLogLevel.INFO,
        farmNo,
        farm.getFarmName(),
        null,
        null,
        null,
        null,
        "FarmDelete",
        null,
        null,
        null);
  }