View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.internal.expectations.argumentMatching;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import mockit.internal.reflection.FieldReflection;
12  
13  import org.hamcrest.Description;
14  import org.hamcrest.Matcher;
15  import org.hamcrest.StringDescription;
16  import org.hamcrest.core.Is;
17  import org.hamcrest.core.IsEqual;
18  import org.hamcrest.core.IsNot;
19  import org.hamcrest.core.IsSame;
20  
21  /**
22   * Adapts the <code>org.hamcrest.Matcher</code> interface to {@link ArgumentMatcher}.
23   */
24  public final class HamcrestAdapter implements ArgumentMatcher<HamcrestAdapter> {
25      @NonNull
26      private final Matcher<?> hamcrestMatcher;
27  
28      public HamcrestAdapter(@NonNull Matcher<?> matcher) {
29          hamcrestMatcher = matcher;
30      }
31  
32      @Override
33      public boolean same(@NonNull HamcrestAdapter other) {
34          return hamcrestMatcher == other.hamcrestMatcher;
35      }
36  
37      @Override
38      public boolean matches(@Nullable Object argValue) {
39          return hamcrestMatcher.matches(argValue);
40      }
41  
42      @Override
43      public void writeMismatchPhrase(@NonNull ArgumentMismatch argumentMismatch) {
44          Description strDescription = new StringDescription();
45          hamcrestMatcher.describeTo(strDescription);
46          argumentMismatch.append(strDescription.toString());
47      }
48  
49      @Nullable
50      public Object getInnerValue() {
51          Object innermostMatcher = getInnermostMatcher();
52          return getArgumentValueFromMatcherIfAvailable(innermostMatcher);
53      }
54  
55      @NonNull
56      private Object getInnermostMatcher() {
57          Matcher<?> innerMatcher = hamcrestMatcher;
58  
59          while (innerMatcher instanceof Is || innerMatcher instanceof IsNot) {
60              innerMatcher = FieldReflection.getField(innerMatcher.getClass(), Matcher.class, innerMatcher);
61          }
62  
63          assert innerMatcher != null;
64          return innerMatcher;
65      }
66  
67      @Nullable
68      private static Object getArgumentValueFromMatcherIfAvailable(@NonNull Object argMatcher) {
69          if (argMatcher instanceof IsEqual || argMatcher instanceof IsSame
70                  || "org.hamcrest.number.OrderingComparison".equals(argMatcher.getClass().getName())) {
71              return FieldReflection.getField(argMatcher.getClass(), Object.class, argMatcher);
72          }
73  
74          return null;
75      }
76  }