/*
*
* * Copyright 2010, Unitils.org
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.unitils.mock.core;
import org.unitils.mock.core.proxy.ProxyInvocation;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tim Ducheyne
* @author Filip Neven
*/
public class BehaviorDefiningInvocations {
protected boolean removeWhenUsed;
protected List<BehaviorDefiningInvocation> behaviorDefiningInvocations = new ArrayList<BehaviorDefiningInvocation>();
public BehaviorDefiningInvocations(boolean removeWhenUsed) {
this.removeWhenUsed = removeWhenUsed;
}
public void addBehaviorDefiningInvocation(BehaviorDefiningInvocation behaviorDefiningInvocation) {
behaviorDefiningInvocations.add(behaviorDefiningInvocation);
}
public void clear() {
behaviorDefiningInvocations.clear();
}
/**
* First we find all behavior defining invocations that have matching argument matchers and take the one with the highest
* matching score (identity match scores higher than an equals match). If there are 2 invocations with the same score,
* we take the invocation with the lowest nr of not-null (default) arguments. If both have the same nr of not-null
* arguments, the first one is returned. E.g.
*
* myMethod(null, null);
* myMethod("a", null);
*
* The second one will be returned if the given proxy invocation has the value "a" as first argument.
*
* @param proxyInvocation The actual invocation to match with, not null
* @return The behavior defining invocation that matches best with the actual invocation, null if none found
*/
public BehaviorDefiningInvocation getMatchingBehaviorDefiningInvocation(ProxyInvocation proxyInvocation) {
BehaviorDefiningInvocation bestMatchingBehaviorDefiningInvocation = null;
int bestMatchingScore = -1;
for (BehaviorDefiningInvocation behaviorDefiningInvocation : behaviorDefiningInvocations) {
int matchingScore = behaviorDefiningInvocation.matches(proxyInvocation);
if (matchingScore == -1) {
// no match
continue;
}
if (matchingScore < bestMatchingScore) {
// there is a better match
continue;
}
if (matchingScore > bestMatchingScore) {
// better match
bestMatchingScore = matchingScore;
bestMatchingBehaviorDefiningInvocation = behaviorDefiningInvocation;
continue;
}
if (matchingScore == bestMatchingScore) {
// same score, nr of not-null values determines the best match
int nrOfNotNullArguments = behaviorDefiningInvocation.getNrOfNotNullArguments();
int bestMatchingNrOfNotNullArguments = bestMatchingBehaviorDefiningInvocation.getNrOfNotNullArguments();
if (nrOfNotNullArguments > bestMatchingNrOfNotNullArguments) {
bestMatchingScore = matchingScore;
bestMatchingBehaviorDefiningInvocation = behaviorDefiningInvocation;
}
}
}
if (removeWhenUsed && bestMatchingBehaviorDefiningInvocation != null) {
behaviorDefiningInvocations.remove(bestMatchingBehaviorDefiningInvocation);
}
return bestMatchingBehaviorDefiningInvocation;
}
}