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;
  }
@ 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}
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 .