/** {@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);
  }
  /** {@inheritDoc} */
  @Override
  public Long createFarm(Long userNo, String farmName, String comment) {
    // 引数チェック
    if (userNo == null) {
      throw new AutoApplicationException("ECOMMON-000003", "userNo");
    }
    if (farmName == null || farmName.length() == 0) {
      throw new AutoApplicationException("ECOMMON-000003", "farmName");
    }

    // 形式チェック
    if (!Pattern.matches("^[0-9a-z]|[0-9a-z][0-9a-z-]*[0-9a-z]$", farmName)) {
      throw new AutoApplicationException("ECOMMON-000012", "farmName");
    }

    // TODO: 長さチェック

    // ファーム名の一意チェック
    Farm checkFarm = farmDao.readByFarmName(farmName);
    if (checkFarm != null) {
      // 同名のファームが存在する場合
      throw new AutoApplicationException("ESERVICE-000201", farmName);
    }

    // ファームのドメイン名
    // TODO: 設定値の取得方法をうまくする
    String domainName = farmName + "." + Config.getProperty("dns.domain");

    // ファームの作成
    Farm farm = new Farm();
    farm.setFarmName(farmName);
    farm.setUserNo(userNo);
    farm.setComment(comment);
    farm.setDomainName(domainName);
    farm.setScheduled(false);
    farm.setComponentProcessing(false);
    farmDao.create(farm);

    // ファームごとのホストグループ作成
    Boolean useZabbix = BooleanUtils.toBooleanObject(Config.getProperty("zabbix.useZabbix"));
    if (BooleanUtils.isTrue(useZabbix)) {
      zabbixHostProcess.createFarmHostgroup(farm.getFarmNo());
    }

    // VMware関連情報の作成
    List<Platform> platforms = platformDao.readAll();
    for (Platform platform : platforms) {
      if ("vmware".equals(platform.getPlatformType()) == false) {
        continue;
      }

      if (vmwareKeyPairDao.countByUserNoAndPlatformNo(userNo, platform.getPlatformNo()) > 0) {
        // 空いているVLANを取得
        VmwareNetwork publicNetwork = null;
        VmwareNetwork privateNetwork = null;
        List<VmwareNetwork> vmwareNetworks =
            vmwareNetworkDao.readByPlatformNo(platform.getPlatformNo());
        for (VmwareNetwork vmwareNetwork : vmwareNetworks) {
          if (vmwareNetwork.getFarmNo() != null) {
            continue;
          }
          if (BooleanUtils.isTrue(vmwareNetwork.getPublicNetwork())) {
            if (publicNetwork == null) {
              publicNetwork = vmwareNetwork;
            }
          } else {
            if (privateNetwork == null) {
              privateNetwork = vmwareNetwork;
            }
          }
        }

        // VLANを割り当て
        if (publicNetwork != null) {
          publicNetwork.setFarmNo(farm.getFarmNo());
          vmwareNetworkDao.update(publicNetwork);
        }
        if (privateNetwork != null) {
          privateNetwork.setFarmNo(farm.getFarmNo());
          vmwareNetworkDao.update(privateNetwork);
        }
      }
    }

    // イベントログ出力
    eventLogger.log(
        EventLogLevel.INFO,
        farm.getFarmNo(),
        farmName,
        null,
        null,
        null,
        null,
        "FarmCreate",
        null,
        null,
        null);

    return farm.getFarmNo();
  }