001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.base;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import com.google.common.annotations.GwtCompatible;
020import com.google.common.annotations.GwtIncompatible;
021import com.google.common.annotations.J2ktIncompatible;
022import java.io.Serializable;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.Collection;
026import java.util.List;
027import java.util.regex.Pattern;
028import org.jspecify.annotations.Nullable;
029
030/**
031 * Static utility methods pertaining to {@code Predicate} instances.
032 *
033 * <p>All methods return serializable predicates as long as they're given serializable parameters.
034 *
035 * <p>See the Guava User Guide article on <a
036 * href="https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code Predicate}</a>.
037 *
038 * @author Kevin Bourrillion
039 * @since 2.0
040 */
041@GwtCompatible(emulated = true)
042public final class Predicates {
043  private Predicates() {}
044
045  // TODO(kevinb): considering having these implement a VisitablePredicate
046  // interface which specifies an accept(PredicateVisitor) method.
047
048  /** Returns a predicate that always evaluates to {@code true}. */
049  @GwtCompatible(serializable = true)
050  public static <T extends @Nullable Object> Predicate<T> alwaysTrue() {
051    return ObjectPredicate.ALWAYS_TRUE.withNarrowedType();
052  }
053
054  /** Returns a predicate that always evaluates to {@code false}. */
055  @GwtCompatible(serializable = true)
056  public static <T extends @Nullable Object> Predicate<T> alwaysFalse() {
057    return ObjectPredicate.ALWAYS_FALSE.withNarrowedType();
058  }
059
060  /**
061   * Returns a predicate that evaluates to {@code true} if the object reference being tested is
062   * null.
063   */
064  @GwtCompatible(serializable = true)
065  public static <T extends @Nullable Object> Predicate<T> isNull() {
066    return ObjectPredicate.IS_NULL.withNarrowedType();
067  }
068
069  /**
070   * Returns a predicate that evaluates to {@code true} if the object reference being tested is not
071   * null.
072   */
073  @GwtCompatible(serializable = true)
074  public static <T extends @Nullable Object> Predicate<T> notNull() {
075    return ObjectPredicate.NOT_NULL.withNarrowedType();
076  }
077
078  /**
079   * Returns a predicate that evaluates to {@code true} if the given predicate evaluates to {@code
080   * false}.
081   */
082  public static <T extends @Nullable Object> Predicate<T> not(Predicate<T> predicate) {
083    return new NotPredicate<>(predicate);
084  }
085
086  /**
087   * Returns a predicate that evaluates to {@code true} if each of its components evaluates to
088   * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
089   * as soon as a false predicate is found. It defensively copies the iterable passed in, so future
090   * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the
091   * returned predicate will always evaluate to {@code true}.
092   */
093  public static <T extends @Nullable Object> Predicate<T> and(
094      Iterable<? extends Predicate<? super T>> components) {
095    return new AndPredicate<>(defensiveCopy(components));
096  }
097
098  /**
099   * Returns a predicate that evaluates to {@code true} if each of its components evaluates to
100   * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
101   * as soon as a false predicate is found. It defensively copies the array passed in, so future
102   * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the
103   * returned predicate will always evaluate to {@code true}.
104   */
105  @SafeVarargs
106  public static <T extends @Nullable Object> Predicate<T> and(Predicate<? super T>... components) {
107    return new AndPredicate<T>(defensiveCopy(components));
108  }
109
110  /**
111   * Returns a predicate that evaluates to {@code true} if both of its components evaluate to {@code
112   * true}. The components are evaluated in order, and evaluation will be "short-circuited" as soon
113   * as a false predicate is found.
114   */
115  public static <T extends @Nullable Object> Predicate<T> and(
116      Predicate<? super T> first, Predicate<? super T> second) {
117    return new AndPredicate<>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
118  }
119
120  /**
121   * Returns a predicate that evaluates to {@code true} if any one of its components evaluates to
122   * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
123   * as soon as a true predicate is found. It defensively copies the iterable passed in, so future
124   * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the
125   * returned predicate will always evaluate to {@code false}.
126   */
127  public static <T extends @Nullable Object> Predicate<T> or(
128      Iterable<? extends Predicate<? super T>> components) {
129    return new OrPredicate<>(defensiveCopy(components));
130  }
131
132  /**
133   * Returns a predicate that evaluates to {@code true} if any one of its components evaluates to
134   * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
135   * as soon as a true predicate is found. It defensively copies the array passed in, so future
136   * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the
137   * returned predicate will always evaluate to {@code false}.
138   */
139  @SafeVarargs
140  public static <T extends @Nullable Object> Predicate<T> or(Predicate<? super T>... components) {
141    return new OrPredicate<T>(defensiveCopy(components));
142  }
143
144  /**
145   * Returns a predicate that evaluates to {@code true} if either of its components evaluates to
146   * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
147   * as soon as a true predicate is found.
148   */
149  public static <T extends @Nullable Object> Predicate<T> or(
150      Predicate<? super T> first, Predicate<? super T> second) {
151    return new OrPredicate<>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
152  }
153
154  /**
155   * Returns a predicate that evaluates to {@code true} if the object being tested {@code equals()}
156   * the given target or both are null.
157   */
158  public static <T extends @Nullable Object> Predicate<T> equalTo(@ParametricNullness T target) {
159    return (target == null)
160        ? Predicates.<T>isNull()
161        : new IsEqualToPredicate(target).withNarrowedType();
162  }
163
164  /**
165   * Returns a predicate that evaluates to {@code true} if the object being tested is an instance of
166   * the given class. If the object being tested is {@code null} this predicate evaluates to {@code
167   * false}.
168   *
169   * <p>If you want to filter an {@code Iterable} to narrow its type, consider using {@link
170   * com.google.common.collect.Iterables#filter(Iterable, Class)} in preference.
171   *
172   * <p><b>Warning:</b> contrary to the typical assumptions about predicates (as documented at
173   * {@link Predicate#apply}), the returned predicate may not be <i>consistent with equals</i>. For
174   * example, {@code instanceOf(ArrayList.class)} will yield different results for the two equal
175   * instances {@code Lists.newArrayList(1)} and {@code Arrays.asList(1)}.
176   */
177  @GwtIncompatible // Class.isInstance
178  public static <T extends @Nullable Object> Predicate<T> instanceOf(Class<?> clazz) {
179    return new InstanceOfPredicate<>(clazz);
180  }
181
182  /**
183   * Returns a predicate that evaluates to {@code true} if the class being tested is assignable to
184   * (is a subtype of) {@code clazz}. Example:
185   *
186   * <pre>{@code
187   * List<Class<?>> classes = Arrays.asList(
188   *     Object.class, String.class, Number.class, Long.class);
189   * return Iterables.filter(classes, subtypeOf(Number.class));
190   * }</pre>
191   *
192   * The code above returns an iterable containing {@code Number.class} and {@code Long.class}.
193   *
194   * @since 20.0 (since 10.0 under the incorrect name {@code assignableFrom})
195   */
196  @J2ktIncompatible
197  @GwtIncompatible // Class.isAssignableFrom
198  public static Predicate<Class<?>> subtypeOf(Class<?> clazz) {
199    return new SubtypeOfPredicate(clazz);
200  }
201
202  /**
203   * Returns a predicate that evaluates to {@code true} if the object reference being tested is a
204   * member of the given collection. It does not defensively copy the collection passed in, so
205   * future changes to it will alter the behavior of the predicate.
206   *
207   * <p>This method can technically accept any {@code Collection<?>}, but using a typed collection
208   * helps prevent bugs. This approach doesn't block any potential users since it is always possible
209   * to use {@code Predicates.<Object>in()}.
210   *
211   * @param target the collection that may contain the function input
212   */
213  @SuppressWarnings("NoHardKeywords") // We're stuck with the name for compatibility reasons.
214  public static <T extends @Nullable Object> Predicate<T> in(Collection<? extends T> target) {
215    return new InPredicate<>(target);
216  }
217
218  /**
219   * Returns the composition of a function and a predicate. For every {@code x}, the generated
220   * predicate returns {@code predicate(function(x))}.
221   *
222   * @return the composition of the provided function and predicate
223   */
224  public static <A extends @Nullable Object, B extends @Nullable Object> Predicate<A> compose(
225      Predicate<B> predicate, Function<A, ? extends B> function) {
226    return new CompositionPredicate<>(predicate, function);
227  }
228
229  /**
230   * Returns a predicate that evaluates to {@code true} if the {@code CharSequence} being tested
231   * contains any match for the given regular expression pattern. The test used is equivalent to
232   * {@code Pattern.compile(pattern).matcher(arg).find()}
233   *
234   * @throws IllegalArgumentException if the pattern is invalid
235   * @since 3.0
236   */
237  @GwtIncompatible // Only used by other GWT-incompatible code.
238  public static Predicate<CharSequence> containsPattern(String pattern) {
239    return new ContainsPatternFromStringPredicate(pattern);
240  }
241
242  /**
243   * Returns a predicate that evaluates to {@code true} if the {@code CharSequence} being tested
244   * contains any match for the given regular expression pattern. The test used is equivalent to
245   * {@code pattern.matcher(arg).find()}
246   *
247   * @since 3.0
248   */
249  @GwtIncompatible(value = "java.util.regex.Pattern")
250  public static Predicate<CharSequence> contains(Pattern pattern) {
251    return new ContainsPatternPredicate(new JdkPattern(pattern));
252  }
253
254  // End public API, begin private implementation classes.
255
256  // Package private for GWT serialization.
257  enum ObjectPredicate implements Predicate<@Nullable Object> {
258    /**
259     * @see Predicates#alwaysTrue()
260     */
261    ALWAYS_TRUE {
262      @Override
263      public boolean apply(@Nullable Object o) {
264        return true;
265      }
266
267      @Override
268      public String toString() {
269        return "Predicates.alwaysTrue()";
270      }
271    },
272    /**
273     * @see Predicates#alwaysFalse()
274     */
275    ALWAYS_FALSE {
276      @Override
277      public boolean apply(@Nullable Object o) {
278        return false;
279      }
280
281      @Override
282      public String toString() {
283        return "Predicates.alwaysFalse()";
284      }
285    },
286    /**
287     * @see Predicates#isNull()
288     */
289    IS_NULL {
290      @Override
291      public boolean apply(@Nullable Object o) {
292        return o == null;
293      }
294
295      @Override
296      public String toString() {
297        return "Predicates.isNull()";
298      }
299    },
300    /**
301     * @see Predicates#notNull()
302     */
303    NOT_NULL {
304      @Override
305      public boolean apply(@Nullable Object o) {
306        return o != null;
307      }
308
309      @Override
310      public String toString() {
311        return "Predicates.notNull()";
312      }
313    };
314
315    @SuppressWarnings("unchecked") // safe contravariant cast
316    <T extends @Nullable Object> Predicate<T> withNarrowedType() {
317      return (Predicate<T>) this;
318    }
319  }
320
321  /**
322   * @see Predicates#not(Predicate)
323   */
324  private static class NotPredicate<T extends @Nullable Object>
325      implements Predicate<T>, Serializable {
326    final Predicate<T> predicate;
327
328    NotPredicate(Predicate<T> predicate) {
329      this.predicate = checkNotNull(predicate);
330    }
331
332    @Override
333    public boolean apply(@ParametricNullness T t) {
334      return !predicate.apply(t);
335    }
336
337    @Override
338    public int hashCode() {
339      return ~predicate.hashCode();
340    }
341
342    @Override
343    public boolean equals(@Nullable Object obj) {
344      if (obj instanceof NotPredicate) {
345        NotPredicate<?> that = (NotPredicate<?>) obj;
346        return predicate.equals(that.predicate);
347      }
348      return false;
349    }
350
351    @Override
352    public String toString() {
353      return "Predicates.not(" + predicate + ")";
354    }
355
356    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
357  }
358
359  /**
360   * @see Predicates#and(Iterable)
361   */
362  private static class AndPredicate<T extends @Nullable Object>
363      implements Predicate<T>, Serializable {
364    private final List<? extends Predicate<? super T>> components;
365
366    private AndPredicate(List<? extends Predicate<? super T>> components) {
367      this.components = components;
368    }
369
370    @Override
371    public boolean apply(@ParametricNullness T t) {
372      // Avoid using the Iterator to avoid generating garbage (issue 820).
373      for (int i = 0; i < components.size(); i++) {
374        if (!components.get(i).apply(t)) {
375          return false;
376        }
377      }
378      return true;
379    }
380
381    @Override
382    public int hashCode() {
383      // add a random number to avoid collisions with OrPredicate
384      return components.hashCode() + 0x12472c2c;
385    }
386
387    @Override
388    public boolean equals(@Nullable Object obj) {
389      if (obj instanceof AndPredicate) {
390        AndPredicate<?> that = (AndPredicate<?>) obj;
391        return components.equals(that.components);
392      }
393      return false;
394    }
395
396    @Override
397    public String toString() {
398      return toStringHelper("and", components);
399    }
400
401    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
402  }
403
404  /**
405   * @see Predicates#or(Iterable)
406   */
407  private static class OrPredicate<T extends @Nullable Object>
408      implements Predicate<T>, Serializable {
409    private final List<? extends Predicate<? super T>> components;
410
411    private OrPredicate(List<? extends Predicate<? super T>> components) {
412      this.components = components;
413    }
414
415    @Override
416    public boolean apply(@ParametricNullness T t) {
417      // Avoid using the Iterator to avoid generating garbage (issue 820).
418      for (int i = 0; i < components.size(); i++) {
419        if (components.get(i).apply(t)) {
420          return true;
421        }
422      }
423      return false;
424    }
425
426    @Override
427    public int hashCode() {
428      // add a random number to avoid collisions with AndPredicate
429      return components.hashCode() + 0x053c91cf;
430    }
431
432    @Override
433    public boolean equals(@Nullable Object obj) {
434      if (obj instanceof OrPredicate) {
435        OrPredicate<?> that = (OrPredicate<?>) obj;
436        return components.equals(that.components);
437      }
438      return false;
439    }
440
441    @Override
442    public String toString() {
443      return toStringHelper("or", components);
444    }
445
446    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
447  }
448
449  private static String toStringHelper(String methodName, Iterable<?> components) {
450    StringBuilder builder = new StringBuilder("Predicates.").append(methodName).append('(');
451    boolean first = true;
452    for (Object o : components) {
453      if (!first) {
454        builder.append(',');
455      }
456      builder.append(o);
457      first = false;
458    }
459    return builder.append(')').toString();
460  }
461
462  /**
463   * @see Predicates#equalTo(Object)
464   */
465  private static class IsEqualToPredicate implements Predicate<@Nullable Object>, Serializable {
466    private final Object target;
467
468    private IsEqualToPredicate(Object target) {
469      this.target = target;
470    }
471
472    @Override
473    public boolean apply(@Nullable Object o) {
474      return target.equals(o);
475    }
476
477    @Override
478    public int hashCode() {
479      return target.hashCode();
480    }
481
482    @Override
483    public boolean equals(@Nullable Object obj) {
484      if (obj instanceof IsEqualToPredicate) {
485        IsEqualToPredicate that = (IsEqualToPredicate) obj;
486        return target.equals(that.target);
487      }
488      return false;
489    }
490
491    @Override
492    public String toString() {
493      return "Predicates.equalTo(" + target + ")";
494    }
495
496    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
497
498    @SuppressWarnings("unchecked") // safe contravariant cast
499    <T extends @Nullable Object> Predicate<T> withNarrowedType() {
500      return (Predicate<T>) this;
501    }
502  }
503
504  /**
505   * @see Predicates#instanceOf(Class)
506   */
507  @GwtIncompatible // Class.isInstance
508  private static class InstanceOfPredicate<T extends @Nullable Object>
509      implements Predicate<T>, Serializable {
510    private final Class<?> clazz;
511
512    private InstanceOfPredicate(Class<?> clazz) {
513      this.clazz = checkNotNull(clazz);
514    }
515
516    @Override
517    public boolean apply(@ParametricNullness T o) {
518      return clazz.isInstance(o);
519    }
520
521    @Override
522    public int hashCode() {
523      return clazz.hashCode();
524    }
525
526    @Override
527    public boolean equals(@Nullable Object obj) {
528      if (obj instanceof InstanceOfPredicate) {
529        InstanceOfPredicate<?> that = (InstanceOfPredicate<?>) obj;
530        return clazz == that.clazz;
531      }
532      return false;
533    }
534
535    @Override
536    public String toString() {
537      return "Predicates.instanceOf(" + clazz.getName() + ")";
538    }
539
540    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
541  }
542
543  /**
544   * @see Predicates#subtypeOf(Class)
545   */
546  @J2ktIncompatible
547  @GwtIncompatible // Class.isAssignableFrom
548  private static class SubtypeOfPredicate implements Predicate<Class<?>>, Serializable {
549    private final Class<?> clazz;
550
551    private SubtypeOfPredicate(Class<?> clazz) {
552      this.clazz = checkNotNull(clazz);
553    }
554
555    @Override
556    public boolean apply(Class<?> input) {
557      return clazz.isAssignableFrom(input);
558    }
559
560    @Override
561    public int hashCode() {
562      return clazz.hashCode();
563    }
564
565    @Override
566    public boolean equals(@Nullable Object obj) {
567      if (obj instanceof SubtypeOfPredicate) {
568        SubtypeOfPredicate that = (SubtypeOfPredicate) obj;
569        return clazz == that.clazz;
570      }
571      return false;
572    }
573
574    @Override
575    public String toString() {
576      return "Predicates.subtypeOf(" + clazz.getName() + ")";
577    }
578
579    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
580  }
581
582  /**
583   * @see Predicates#in(Collection)
584   */
585  private static class InPredicate<T extends @Nullable Object>
586      implements Predicate<T>, Serializable {
587    private final Collection<?> target;
588
589    private InPredicate(Collection<?> target) {
590      this.target = checkNotNull(target);
591    }
592
593    @Override
594    public boolean apply(@ParametricNullness T t) {
595      try {
596        return target.contains(t);
597      } catch (NullPointerException | ClassCastException e) {
598        return false;
599      }
600    }
601
602    @Override
603    /*
604     * We should probably not have implemented equals() at all, but given that we did, we can't
605     * provide a better implementation than the input Collection, at least without dramatic changes
606     * like copying it to a new Set—which might then test for element equality differently.
607     */
608    @SuppressWarnings("UndefinedEquals")
609    public boolean equals(@Nullable Object obj) {
610      if (obj instanceof InPredicate) {
611        InPredicate<?> that = (InPredicate<?>) obj;
612        return target.equals(that.target);
613      }
614      return false;
615    }
616
617    @Override
618    public int hashCode() {
619      return target.hashCode();
620    }
621
622    @Override
623    public String toString() {
624      return "Predicates.in(" + target + ")";
625    }
626
627    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
628  }
629
630  /**
631   * @see Predicates#compose(Predicate, Function)
632   */
633  private static class CompositionPredicate<A extends @Nullable Object, B extends @Nullable Object>
634      implements Predicate<A>, Serializable {
635    final Predicate<B> p;
636    final Function<A, ? extends B> f;
637
638    private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) {
639      this.p = checkNotNull(p);
640      this.f = checkNotNull(f);
641    }
642
643    @Override
644    public boolean apply(@ParametricNullness A a) {
645      return p.apply(f.apply(a));
646    }
647
648    @Override
649    public boolean equals(@Nullable Object obj) {
650      if (obj instanceof CompositionPredicate) {
651        CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
652        return f.equals(that.f) && p.equals(that.p);
653      }
654      return false;
655    }
656
657    @Override
658    public int hashCode() {
659      return f.hashCode() ^ p.hashCode();
660    }
661
662    @Override
663    public String toString() {
664      // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
665      return p + "(" + f + ")";
666    }
667
668    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
669  }
670
671  /**
672   * @see Predicates#contains(Pattern)
673   */
674  @GwtIncompatible // Only used by other GWT-incompatible code.
675  private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
676    final CommonPattern pattern;
677
678    ContainsPatternPredicate(CommonPattern pattern) {
679      this.pattern = checkNotNull(pattern);
680    }
681
682    @Override
683    public boolean apply(CharSequence t) {
684      return pattern.matcher(t).find();
685    }
686
687    @Override
688    public int hashCode() {
689      // Pattern uses Object.hashCode, so we have to reach
690      // inside to build a hashCode consistent with equals.
691
692      return Objects.hashCode(pattern.pattern(), pattern.flags());
693    }
694
695    @Override
696    public boolean equals(@Nullable Object obj) {
697      if (obj instanceof ContainsPatternPredicate) {
698        ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
699
700        // Pattern uses Object (identity) equality, so we have to reach
701        // inside to compare individual fields.
702        return Objects.equal(pattern.pattern(), that.pattern.pattern())
703            && pattern.flags() == that.pattern.flags();
704      }
705      return false;
706    }
707
708    @Override
709    public String toString() {
710      String patternString =
711          MoreObjects.toStringHelper(pattern)
712              .add("pattern", pattern.pattern())
713              .add("pattern.flags", pattern.flags())
714              .toString();
715      return "Predicates.contains(" + patternString + ")";
716    }
717
718    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
719  }
720
721  /**
722   * @see Predicates#containsPattern(String)
723   */
724  @GwtIncompatible // Only used by other GWT-incompatible code.
725  private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
726
727    ContainsPatternFromStringPredicate(String string) {
728      super(Platform.compilePattern(string));
729    }
730
731    @Override
732    public String toString() {
733      return "Predicates.containsPattern(" + pattern.pattern() + ")";
734    }
735
736    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
737  }
738
739  private static <T extends @Nullable Object> List<Predicate<? super T>> asList(
740      Predicate<? super T> first, Predicate<? super T> second) {
741    // TODO(kevinb): understand why we still get a warning despite @SafeVarargs!
742    return Arrays.<Predicate<? super T>>asList(first, second);
743  }
744
745  private static <T> List<T> defensiveCopy(T... array) {
746    return defensiveCopy(Arrays.asList(array));
747  }
748
749  static <T> List<T> defensiveCopy(Iterable<T> iterable) {
750    ArrayList<T> list = new ArrayList<>();
751    for (T element : iterable) {
752      list.add(checkNotNull(element));
753    }
754    return list;
755  }
756}