/**
   * Link the target volumes to the passed in source volume
   *
   * @param unManagedProtectionSet unmanaged protection set
   * @param sourceVolume RP CG source volume
   * @param rset RP CG replication set
   * @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
   * @return rpTargetVolumeIds Set of unmanaged target volume ids for the given source volume
   */
  private StringSet linkTargetVolumes(
      UnManagedProtectionSet unManagedProtectionSet,
      UnManagedVolume sourceVolume,
      GetRSetResponse rset,
      Map<String, String> rpWwnToNativeWwn,
      List<String> storageNativeIdPrefixes,
      DbClient dbClient) {
    StringSet rpTargetVolumeIds = new StringSet();
    // Find the target volumes associated with this source volume.
    for (GetVolumeResponse targetVolume : rset.getVolumes()) {
      // Find this volume in UnManagedVolumes based on wwn
      UnManagedVolume targetUnManagedVolume = null;
      String targetWwn = rpWwnToNativeWwn.get(targetVolume.getWwn());
      if (targetWwn != null) {
        targetUnManagedVolume =
            findUnManagedVolumeForWwn(targetWwn, dbClient, storageNativeIdPrefixes);
      }

      if (null == targetUnManagedVolume) {
        log.info(
            "Protection Set {} contains unknown target volume: {}. Skipping.",
            unManagedProtectionSet.getNativeGuid(),
            targetVolume.getWwn());
        continue;
      }

      // Don't bother if we just re-found the source device
      if (targetUnManagedVolume.getId().equals(sourceVolume.getId())) {
        continue;
      }

      // Check if this volume is already managed, which would indicate it has already been partially
      // ingested
      Volume targetManagedVolume =
          DiscoveryUtils.checkManagedVolumeExistsInDBByWwn(dbClient, targetVolume.getWwn());
      if (null != targetManagedVolume) {
        log.info(
            "Protection Set {} has an orphaned unmanaged target volume {}. Skipping.",
            unManagedProtectionSet.getNativeGuid(),
            targetUnManagedVolume.getLabel());
        continue;
      }
      log.info("\tfound target volume {}", targetUnManagedVolume.forDisplay());

      // Add the source unmanaged volume ID to the target volume
      StringSet rpUnManagedSourceVolumeId = new StringSet();
      rpUnManagedSourceVolumeId.add(sourceVolume.getId().toString());
      targetUnManagedVolume.putVolumeInfo(
          SupportedVolumeInformation.RP_UNMANAGED_SOURCE_VOLUME.toString(),
          rpUnManagedSourceVolumeId);

      // Update the target unmanaged volume with the source managed volume ID
      unManagedVolumesToUpdateByWwn.put(targetUnManagedVolume.getWwn(), targetUnManagedVolume);

      // Store the unmanaged target ID in the source volume
      rpTargetVolumeIds.add(targetUnManagedVolume.getId().toString());
    }

    return rpTargetVolumeIds;
  }
  /**
   * Clean up the existing unmanaged protection set and its associated unmanaged volumes so that it
   * gets updated with latest info during rediscovery
   *
   * @param unManagedProtectionSet unmanaged protection set
   * @param unManagedVolumesToUpdateByWwn unmanaged volumes to update
   * @param dbClient db client
   */
  private void cleanUpUnManagedResources(
      UnManagedProtectionSet unManagedProtectionSet,
      Map<String, UnManagedVolume> unManagedVolumesToUpdateByWwn,
      DbClient dbClient) {
    // Clean up the volume wwns, managed volume and unmanaged volume lists of the unmanaged
    // protection set
    unManagedProtectionSet.getManagedVolumeIds().clear();
    unManagedProtectionSet.getVolumeWwns().clear();
    List<URI> unManagedVolsUris =
        new ArrayList<URI>(
            Collections2.transform(
                unManagedProtectionSet.getUnManagedVolumeIds(),
                CommonTransformerFunctions.FCTN_STRING_TO_URI));
    Iterator<UnManagedVolume> unManagedVolsOfProtectionSetIter =
        dbClient.queryIterativeObjects(UnManagedVolume.class, unManagedVolsUris);
    while (unManagedVolsOfProtectionSetIter.hasNext()) {
      UnManagedVolume rpUnManagedVolume = unManagedVolsOfProtectionSetIter.next();
      // Clear the RP related fields in the UnManagedVolume
      StringSet rpPersonality =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_PERSONALITY.toString());
      StringSet rpCopyName =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_COPY_NAME.toString());
      StringSet rpInternalSiteName =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_INTERNAL_SITENAME.toString());
      StringSet rpProtectionSystem =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_PROTECTIONSYSTEM.toString());
      StringSet rpSourceVol =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_UNMANAGED_SOURCE_VOLUME.toString());
      StringSet rpTargetVols =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_UNMANAGED_TARGET_VOLUMES.toString());
      StringSet rpAccessState =
          rpUnManagedVolume
              .getVolumeInformation()
              .get(SupportedVolumeInformation.RP_ACCESS_STATE.toString());

      if (rpPersonality != null) {
        rpPersonality.clear();
      }
      if (rpCopyName != null) {
        rpCopyName.clear();
      }
      if (rpInternalSiteName != null) {
        rpInternalSiteName.clear();
      }
      if (rpProtectionSystem != null) {
        rpProtectionSystem.clear();
      }
      if (rpSourceVol != null) {
        rpSourceVol.clear();
      }
      if (rpTargetVols != null) {
        rpTargetVols.clear();
      }
      if (rpAccessState != null) {
        rpAccessState.clear();
      }
      unManagedVolumesToUpdateByWwn.put(rpUnManagedVolume.getWwn(), rpUnManagedVolume);
    }

    unManagedProtectionSet.getUnManagedVolumeIds().clear();
  }