private String getFlattenedValue(Map<String, Interest> input) {
    StringBuilder stringBuilder = new StringBuilder();
    Set<Map.Entry<String, Interest>> inputEntrySet = input.entrySet();
    Iterator<Map.Entry<String, Interest>> iterator = inputEntrySet.iterator();

    int numEntries = input.size();
    int currentIndex = 0;
    for (Map.Entry<String, Interest> entry : input.entrySet()) {
      String key = entry.getKey();
      Interest interest = entry.getValue();
      if (key == null
          || key.isEmpty()
          || interest == null
          || interest.getValue() == null
          || interest.getValue().isEmpty()) {
        continue;
      }
      String interestStr = interest.getValue();
      stringBuilder.append(key);
      stringBuilder.append("_");
      stringBuilder.append(interestStr);
      if (currentIndex++ != numEntries - 1) {
        stringBuilder.append(" ");
      }
    }

    return stringBuilder.toString();
  }
  public void destroy() throws Exception {
    Region<K, V> region = getObject();
    // unregister interests
    try {
      if (region != null && !ObjectUtils.isEmpty(interests)) {
        for (Interest<K> interest : interests) {
          if (interest instanceof RegexInterest) {
            region.unregisterInterestRegex((String) interest.getKey());
          } else {
            region.unregisterInterest(interest.getKey());
          }
        }
      }
      // should not really happen since interests are validated at start/registration
    } catch (UnsupportedOperationException ex) {
      log.warn("Cannot unregister cache interests", ex);
    }

    if (region != null) {
      if (close) {
        if (!region.getCache().isClosed()) {
          try {
            region.close();
          } catch (CacheClosedException cce) {
            // nothing to see folks, move on.
          }
        }
      } else if (destroy) {
        region.destroyRegion();
      }
    }
    region = null;
  }
  /**
   * Remove all references to the channel. 1) the map of a channel (socket) to its interests. 2) the
   * map of interests to its channels.
   *
   * <p>As each interest is removed inform all channels having a similar interest.
   *
   * @param sourceCtx
   */
  public void unregister(final ChannelHandlerContext sourceCtx) {
    final SocketAddress key = sourceCtx.channel().remoteAddress();
    majorLogger.info("unregister channel {}", key);
    final Interest.ChannelInterestSet channelInterestSet = this.channelInterestMap.remove(key);
    if (channelInterestSet == null) {
      majorLogger.warn(
          "nothing to unregister in interest map: {}", this.channelInterestMap.keySet());
      return;
    }
    final String trackingGuid = UUID.randomUUID().toString();
    majorLogger.warn("no interested channel set");

    for (final Interest interest : channelInterestSet.getInterestList()) {
      if (!this.interestedChannelMap.containsKey(interest)) {
        continue;
      }

      final Interest.InterestedChannelSet interestedChannelSet =
          this.interestedChannelMap.get(interest);
      interestedChannelSet.removeItem(sourceCtx, interest);
      majorLogger.info("unregistered interest {}", interest);
      // this.interestedChannelMap.put(interest, interestedChannelSet);

      // an implicit DISINTEREST message will be sent to all interested channels

      final MetaLinkMsg.Edit.Builder editBuilder =
          MetaLinkMsg.Edit.newBuilder()
              .addMode(MetaLinkMsg.Edit.EditMode.DISINTEREST)
              .setEditMode(MetaLinkMsg.Edit.EditMode.DISINTEREST)
              .setGuid(trackingGuid)
              .setSequence(sequenceNumber.incrementAndGet())
              .addAllTopic(interest.getTopic())
              .addOrigin(sourceCtx.channel().remoteAddress().toString())
              .addOrigin(METALINK_BRIDGE_NAME);
      final MetaLinkMsg.Edit disinterestMsg = editBuilder.build();

      majorLogger.trace("expressing disinterest to all channels except source");
      for (final Map.Entry<SocketAddress, Interest.ChannelInterestSet> entry :
          this.channelInterestMap.entrySet()) {
        final ChannelHandlerContext ctx = entry.getValue().context;
        if (isSameChannel(ctx, sourceCtx)) {
          continue;
        }
        majorLogger.trace("disinterest {} to {}", trackingGuid, ctx.channel().remoteAddress());
        ctx.write(disinterestMsg);
        ctx.flush();
        detailLogger.info("message sent:\n{}", disinterestMsg);
      }
    }
  }
 protected void postProcess(Region<K, V> region) {
   if (!ObjectUtils.isEmpty(interests)) {
     for (Interest<K> interest : interests) {
       if (interest instanceof RegexInterest) {
         // do the cast since it's safe
         region.registerInterestRegex(
             (String) interest.getKey(),
             interest.getPolicy(),
             interest.isDurable(),
             interest.isReceiveValues());
       } else {
         region.registerInterest(
             interest.getKey(),
             interest.getPolicy(),
             interest.isDurable(),
             interest.isReceiveValues());
       }
     }
   }
 }