Home | History | Annotate | Download | only in filter
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockito.internal.configuration.injection.filter;
      6 
      7 import static org.mockito.internal.util.MockUtil.getMockName;
      8 
      9 import java.lang.reflect.Field;
     10 import java.util.ArrayList;
     11 import java.util.Collection;
     12 import java.util.List;
     13 
     14 public class NameBasedCandidateFilter implements MockCandidateFilter {
     15     private final MockCandidateFilter next;
     16 
     17     public NameBasedCandidateFilter(MockCandidateFilter next) {
     18         this.next = next;
     19     }
     20 
     21     public OngoingInjector filterCandidate(final Collection<Object> mocks,
     22                                            final Field candidateFieldToBeInjected,
     23                                            final List<Field> allRemainingCandidateFields,
     24                                            final Object injectee) {
     25         if (mocks.size() == 1
     26                 && anotherCandidateMatchesMockName(mocks, candidateFieldToBeInjected, allRemainingCandidateFields)) {
     27             return OngoingInjector.nop;
     28         }
     29 
     30         return next.filterCandidate(tooMany(mocks) ? selectMatchingName(mocks, candidateFieldToBeInjected) : mocks,
     31                                     candidateFieldToBeInjected,
     32                                     allRemainingCandidateFields,
     33                                     injectee);
     34     }
     35 
     36     private boolean tooMany(Collection<Object> mocks) {
     37         return mocks.size() > 1;
     38     }
     39 
     40     private List<Object> selectMatchingName(Collection<Object> mocks, Field candidateFieldToBeInjected) {
     41         List<Object> mockNameMatches = new ArrayList<Object>();
     42         for (Object mock : mocks) {
     43             if (candidateFieldToBeInjected.getName().equals(getMockName(mock).toString())) {
     44                 mockNameMatches.add(mock);
     45             }
     46         }
     47         return mockNameMatches;
     48     }
     49 
     50     /*
     51      * In this case we have to check whether we have conflicting naming
     52      * fields. E.g. 2 fields of the same type, but we have to make sure
     53      * we match on the correct name.
     54      *
     55      * Therefore we have to go through all other fields and make sure
     56      * whenever we find a field that does match its name with the mock
     57      * name, we should take that field instead.
     58      */
     59     private boolean anotherCandidateMatchesMockName(final Collection<Object> mocks,
     60                                                     final Field candidateFieldToBeInjected,
     61                                                     final List<Field> allRemainingCandidateFields) {
     62         String mockName = getMockName(mocks.iterator().next()).toString();
     63 
     64         for (Field otherCandidateField : allRemainingCandidateFields) {
     65             if (!otherCandidateField.equals(candidateFieldToBeInjected)
     66                     && otherCandidateField.getType().equals(candidateFieldToBeInjected.getType())
     67                     && otherCandidateField.getName().equals(mockName)) {
     68                 return true;
     69             }
     70         }
     71         return false;
     72     }
     73 }
     74