1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5
6package org.mockito.internal.progress;
7
8import org.mockito.ArgumentMatcher;
9import org.mockito.internal.matchers.And;
10import org.mockito.internal.matchers.LocalizedMatcher;
11import org.mockito.internal.matchers.Not;
12import org.mockito.internal.matchers.Or;
13
14import static java.util.Collections.emptyList;
15import static org.mockito.internal.exceptions.Reporter.incorrectUseOfAdditionalMatchers;
16import static org.mockito.internal.exceptions.Reporter.misplacedArgumentMatcher;
17import static org.mockito.internal.exceptions.Reporter.reportNoSubMatchersFound;
18
19import java.util.*;
20
21public class ArgumentMatcherStorageImpl implements ArgumentMatcherStorage {
22
23    private static final int TWO_SUB_MATCHERS = 2;
24    private static final int ONE_SUB_MATCHER = 1;
25    private final Stack<LocalizedMatcher> matcherStack = new Stack<LocalizedMatcher>();
26
27    public void reportMatcher(ArgumentMatcher<?> matcher) {
28        matcherStack.push(new LocalizedMatcher(matcher));
29    }
30
31    public List<LocalizedMatcher> pullLocalizedMatchers() {
32        if (matcherStack.isEmpty()) {
33            return emptyList();
34        }
35
36        List<LocalizedMatcher> lastMatchers = resetStack();
37        return lastMatchers;
38    }
39
40    public void reportAnd() {
41        assertStateFor("And(?)", TWO_SUB_MATCHERS);
42
43        ArgumentMatcher<?> m1 = popMatcher();
44        ArgumentMatcher<?> m2 = popMatcher();
45
46        reportMatcher(new And(m1, m2));
47    }
48
49    public void reportOr() {
50        assertStateFor("Or(?)", TWO_SUB_MATCHERS);
51
52        ArgumentMatcher<?> m1 = popMatcher();
53        ArgumentMatcher<?> m2 = popMatcher();
54
55        reportMatcher(new Or(m1, m2));
56    }
57
58    public void reportNot() {
59        assertStateFor("Not(?)", ONE_SUB_MATCHER);
60
61        ArgumentMatcher<?> m = popMatcher();
62
63        reportMatcher(new Not(m));
64    }
65
66    public void validateState() {
67        if (!matcherStack.isEmpty()) {
68            List<LocalizedMatcher> lastMatchers = resetStack();
69            throw misplacedArgumentMatcher(lastMatchers);
70        }
71    }
72
73    public void reset() {
74        matcherStack.clear();
75    }
76
77    private void assertStateFor(String additionalMatcherName, int subMatchersCount) {
78        if (matcherStack.isEmpty()) {
79            throw reportNoSubMatchersFound(additionalMatcherName);
80        }
81        if (matcherStack.size() < subMatchersCount) {
82            List<LocalizedMatcher> lastMatchers = resetStack();
83            throw incorrectUseOfAdditionalMatchers(additionalMatcherName, subMatchersCount, lastMatchers);
84        }
85    }
86
87    private ArgumentMatcher<?> popMatcher() {
88        return matcherStack.pop().getMatcher();
89    }
90
91    private List<LocalizedMatcher> resetStack() {
92        ArrayList<LocalizedMatcher> lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
93        reset();
94        return lastMatchers;
95    }
96
97}
98