openrtb-core/src/main/java/com/google/openrtb/util/ProtoUtils.java
@Nullable public static <M extends Message> M filter(
      M msg, boolean clearEmpty, Predicate<FieldDescriptor> filter) {
    checkNotNull(filter);

    int i = 0;
    for (Map.Entry<FieldDescriptor, Object> entry : msg.getAllFields().entrySet()) {
      FieldDescriptor fd = entry.getKey();

      if (!filter.test(fd)) {
        // At least one field discarded, go to slow-path.
        return filterFrom(msg, clearEmpty, filter, i, true);
      } else if (fd.getType() == FieldDescriptor.Type.MESSAGE) {
        // At least one field may have children, go to slow-path.
        return filterFrom(msg, clearEmpty, filter, i, false);
      }

      ++i;
    }

    // Optimized common case: all items filtered, return the input sequence.
    return msg;
  }
@Nullable public static <M extends Message> M filter(
      M msg, boolean clearEmpty, Predicate<FieldDescriptor> filter) {
    checkNotNull(filter);

    int i = 0;
    for (Map.Entry<FieldDescriptor, Object> entry : msg.getAllFields().entrySet()) {
      FieldDescriptor fd = entry.getKey();

      if (!filter.test(fd)) {
        // At least one field discarded, go to slow-path.
        return filterFrom(msg, clearEmpty, filter, i, true);
      } else if (fd.getType() == FieldDescriptor.Type.MESSAGE) {
        // At least one field may have children, go to slow-path.
        return filterFrom(msg, clearEmpty, filter, i, false);
      }

      ++i;
    }

    // Optimized common case: all items filtered, return the input sequence.
    return msg;
  }
Returns a copy of a {@link Message} that contains only fields that pass a filter.
This will be executed recursively for fields which are child messages.

@param msg Message object
@param clearEmpty {@code true} will cause {@code null} to be returned if all fields from
{@code msg} are removed; {@code false} will return an "empty" message in that case
@param filter Function that returns {@code true} to retain a field, {@code false} to discard
@return Message with the retained fieldsfrom {@code msg}.
If some fields are retained and others discarded, returns a new message object.
If all fields are retained, returns the same {@code msg} object.
If all fields are discarded, returns {@code null} if {@code clearEmpty==true}
or a default instance of {@code msg}'s message type if {@code clearEmpty==false}