/**
   * Filter vpools from the qualified list. rpSource true: Filter out anything other than RP source
   * vpools rpSource false: Filter out RP and SRDF source vpools
   *
   * @param dbClient dbclient
   * @param unManagedVolume unmanaged volume
   * @param personality SOURCE, TARGET, or METADATA
   */
  private void filterProtectedVpools(
      DbClient dbClient, UnManagedVolume unManagedVolume, String personality) {

    if (unManagedVolume.getSupportedVpoolUris() != null
        && !unManagedVolume.getSupportedVpoolUris().isEmpty()) {
      Iterator<VirtualPool> vpoolItr =
          dbClient.queryIterativeObjects(
              VirtualPool.class, URIUtil.toURIList(unManagedVolume.getSupportedVpoolUris()));
      while (vpoolItr.hasNext()) {
        boolean remove = false;
        VirtualPool vpool = vpoolItr.next();

        // If this is an SRDF source vpool, we can filter out since we're dealing with an RP volume
        if (vpool.getProtectionRemoteCopySettings() != null) {
          remove = true;
        }

        // If this is not an RP source, the vpool should be filtered out if:
        // The vpool is an RP vpool (has settings) and target vpools are non-null
        if (vpool.getProtectionVarraySettings() != null
            && ((Volume.PersonalityTypes.TARGET.name().equalsIgnoreCase(personality))
                || Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality))) {
          boolean foundEmptyTargetVpool = false;
          Map<URI, VpoolProtectionVarraySettings> settings =
              VirtualPool.getProtectionSettings(vpool, dbClient);
          for (Map.Entry<URI, VpoolProtectionVarraySettings> setting : settings.entrySet()) {
            if (NullColumnValueGetter.isNullURI(setting.getValue().getVirtualPool())) {
              foundEmptyTargetVpool = true;
              break;
            }
          }

          // If this is a journal volume, also check the journal vpools. If they're not set, we
          // cannot filter out this vpool.
          if (Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality)
              && (NullColumnValueGetter.isNullValue(vpool.getJournalVpool())
                  || NullColumnValueGetter.isNullValue(vpool.getStandbyJournalVpool()))) {
            foundEmptyTargetVpool = true;
          }

          // If every relevant target (and journal for journal volumes) vpool is filled-in, then
          // you would never assign your target volume to this source vpool, so filter it out.
          if (!foundEmptyTargetVpool) {
            remove = true;
          }
        }

        if (Volume.PersonalityTypes.SOURCE.name().equalsIgnoreCase(personality)) {
          if (!VirtualPool.vPoolSpecifiesProtection(vpool)) {
            // If this an RP source, the vpool must be an RP vpool
            remove = true;
          } else if (unManagedVolume
                  .getVolumeInformation()
                  .containsKey(SupportedVolumeInformation.RP_STANDBY_INTERNAL_SITENAME.toString())
              && !VirtualPool.vPoolSpecifiesMetroPoint(vpool)) {
            // Since this is a Source volume with the presence of RP_STANDBY_INTERNAL_SITENAME
            // it indicates that this volume is MetroPoint, if we get here, this is vpool
            // must be filtered out since it's not MP.
            remove = true;
          }
        }

        if (remove) {
          log.info(
              "Removing virtual pool "
                  + vpool.getLabel()
                  + " from supported vpools for unmanaged volume: "
                  + unManagedVolume.getLabel());
          unManagedVolume.getSupportedVpoolUris().remove(vpool.getId().toString());
        }
      }
    }
  }
  /**
   * Update (if it exists) the journal UnManagedVolume objects with RP information needed for
   * ingestion
   *
   * @param unManagedProtectionSet unmanaged protection set
   * @param cg CG response got back from RP system
   * @param rpCopyAccessStateMap Map to hold the access state of the replication sets.
   * @param rpWwnToNativeWwn Map of RP volume WWN to native volume WWN - required for XIO but
   *     harmless otherwise
   * @param storageNativeIdPrefixes List of XIO systems discovered in ViPR
   * @param dbClient DB client instance
   */
  private void mapCgJournals(
      UnManagedProtectionSet unManagedProtectionSet,
      GetCGsResponse cg,
      Map<String, String> rpCopyAccessStateMap,
      Map<String, String> rpWwnToNativeWwn,
      List<String> storageNativeIdPrefixes,
      DbClient dbClient) {
    for (GetCopyResponse copy : cg.getCopies()) {
      String accessState = copy.getAccessState();
      for (GetVolumeResponse volume : copy.getJournals()) {
        // Find this volume in UnManagedVolumes based on wwn
        UnManagedVolume unManagedVolume =
            findUnManagedVolumeForWwn(volume.getWwn(), dbClient, storageNativeIdPrefixes);

        // Check if this volume is already managed, which would indicate it has already been
        // partially ingested
        Volume managedVolume =
            DiscoveryUtils.checkManagedVolumeExistsInDBByWwn(dbClient, volume.getWwn());

        // Add the WWN to the unmanaged protection set, regardless of whether this volume is
        // unmanaged or not.
        unManagedProtectionSet.getVolumeWwns().add(volume.getWwn());

        if (null == unManagedVolume && null == managedVolume) {
          log.info(
              "Protection Set {} contains unknown Journal volume: {}. Skipping.",
              unManagedProtectionSet.getNativeGuid(),
              volume.getWwn());
          continue;
        }

        if (null != managedVolume) {
          log.info(
              "Protection Set {} contains volume {} that is already managed",
              unManagedProtectionSet.getNativeGuid(),
              volume.getWwn());
          // make sure it's in the UnManagedProtectionSet's ManagedVolume ids
          if (!unManagedProtectionSet
              .getManagedVolumeIds()
              .contains(managedVolume.getId().toString())) {
            unManagedProtectionSet.getManagedVolumeIds().add(managedVolume.getId().toString());
          }

          if (null != unManagedVolume) {
            log.info(
                "Protection Set {} also has an orphaned UnManagedVolume {} that will be removed",
                unManagedProtectionSet.getNativeGuid(),
                unManagedVolume.getLabel());
            // remove the unManagedVolume from the UnManagedProtectionSet's UnManagedVolume ids
            unManagedProtectionSet
                .getUnManagedVolumeIds()
                .remove(unManagedVolume.getId().toString());
            unManagedVolumesToDelete.add(unManagedVolume);
          }

          // because this volume is already managed, we can just continue to the next
          continue;
        }

        // at this point, we have an legitimate UnManagedVolume whose RP properties should be
        // updated
        log.info("Processing Journal UnManagedVolume {}", unManagedVolume.forDisplay());

        // Capture the access state
        rpCopyAccessStateMap.put(volume.getRpCopyName(), accessState);

        // Add the unmanaged volume to the list (if it's not there already)
        if (!unManagedProtectionSet
            .getUnManagedVolumeIds()
            .contains(unManagedVolume.getId().toString())) {
          unManagedProtectionSet.getUnManagedVolumeIds().add(unManagedVolume.getId().toString());
        }

        updateCommonRPProperties(
            unManagedProtectionSet,
            unManagedVolume,
            Volume.PersonalityTypes.METADATA.name(),
            volume,
            dbClient);

        rpWwnToNativeWwn.put(volume.getWwn(), unManagedVolume.getWwn());

        unManagedVolumesToUpdateByWwn.put(unManagedVolume.getWwn(), unManagedVolume);
      }
    }
  }