@Override
	public int compare(Invocation c1, Invocation c2) {
		MethodCall o1 = c1.getMethodCall();
		MethodCall o2 = c2.getMethodCall();
		// First compare on names
		{
			int value = comp(nameMatches(o1), nameMatches(o2));
			if (value != 0) {
				return value;
			}
		}

		// Compare on method signature
		{
			int value = comp(methodMatches(o1), methodMatches(o2));
			if (value != 0) {
				return value;
			}
		}


		// Compare on actual arguments and types
		{
			Class[] parameters = method.getParameters();

			int i = 0;
			for (Matcher matcher : argumentMatchers) {
				int value = comp(matchNull(o1, i), matchNull(o2, i));
				if (value != 0) {
					return value;
				}

				value = comp(matchArg(o1, i, matcher), matchArg(o2, i, matcher));
				if (value != 0) {
					return value;
				}

				value = comp(matchType(o1, i, parameters), matchType(o1, i, parameters));
				if (value != 0) {
					return value;
				}

				i++;
			}
		}

		// Compare number of arguments
		int value = comp(compareLength(o1), compareLength(o2));
		if (value != 0) {
			return value;
		}

		// Compare number of arguments
		int len1 = getNumArgs(o1);
		int len2 = getNumArgs(o2);
		if (len1 < len2) {
			return -1;
		}
		if (len1 > len2) {
			return 1;
		}

		// Compare on argument hashcodes in order to put equal
		// argument lists next to each other

		return compareOrigin(c1, c2);

	}