1 /*******************************************************************************
2 * Copyright 2013 André Rouél and Dominik Seichter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16 package net.sf.qualitycheck.exception;
17
18 import javax.annotation.Nullable;
19
20 /**
21 * Thrown to indicate that a method has been passed with a reference of an unexpected type.
22 *
23 * @author André Rouél
24 * @author Dominik Seichter
25 */
26 public class IllegalInstanceOfArgumentException extends RuntimeException {
27
28 private static final long serialVersionUID = -1886931952915327794L;
29
30 /**
31 * Default message to indicate that a given argument must is a member of an unexpected type
32 */
33 protected static final String DEFAULT_MESSAGE = "The passed argument is a member of an unexpected type.";
34
35 /**
36 * Message to indicate that a given argument with must is a member of an unexpected type (with current and expected
37 * type information)
38 */
39 protected static final String MESSAGE_WITH_TYPES = "The passed argument is a member of an unexpected type (expected type: %s, actual: %s).";
40
41 /**
42 * Message to indicate that a given argument with <em>name</em> must is a member of an unexpected type (with current
43 * and expected type information)
44 */
45 protected static final String MESSAGE_WITH_NAME_AND_TYPES = "The passed argument '%s' is a member of an unexpected type (expected type: %s, actual: %s).";
46
47 /**
48 * Placeholder for not set types to format a message human readable
49 */
50 protected static final String NO_TYPE_PLACEHOLDER = "(not set)";
51
52 /**
53 * Determines the message to be used, depending on the passed argument name. If if the given argument name is
54 * {@code null} or empty {@code DEFAULT_MESSAGE} will be returned, otherwise a formatted {@code MESSAGE_WITH_NAME}
55 * with the passed name.
56 *
57 * @param argumentName
58 * the name of the passed argument
59 * @param expectedType
60 * the expected class of the given argument
61 * @param actualType
62 * the actual class of the given argument
63 * @return {@code MESSAGE_WITH_TYPES} if the given argument name is {@code null} or empty, otherwise a formatted
64 * {@code MESSAGE_WITH_NAME}
65 */
66 private static String determineMessage(@Nullable final String argumentName, @Nullable final Class<?> expectedType,
67 @Nullable final Class<?> actualType) {
68 return argumentName != null && !argumentName.isEmpty() ? format(argumentName, expectedType, actualType) : format(expectedType,
69 actualType);
70 }
71
72 /**
73 * Returns the formatted string {@link IllegalInstanceOfArgumentException#MESSAGE_WITH_TYPES} with the given types.
74 *
75 * @param expectedType
76 * the expected class of the given argument
77 * @param actualType
78 * the actual class of the given argument
79 * @return a formatted string of message with the given argument name
80 */
81 private static String format(@Nullable final Class<?> expectedType, @Nullable final Class<?> actualType) {
82 final String expected = expectedType != null ? expectedType.getName() : NO_TYPE_PLACEHOLDER;
83 final String actual = actualType != null ? actualType.getName() : NO_TYPE_PLACEHOLDER;
84 return String.format(MESSAGE_WITH_TYPES, expected, actual);
85 }
86
87 /**
88 * Returns the formatted string {@link IllegalInstanceOfArgumentException#MESSAGE_WITH_NAME_AND_TYPES} with the
89 * given {@code argumentName}.
90 *
91 * @param argumentName
92 * the name of the passed argument
93 * @param expectedType
94 * the expected class of the given argument
95 * @param actualType
96 * the actual class of the given argument
97 * @return a formatted string of message with the given argument name
98 */
99 private static String format(@Nullable final String argumentName, @Nullable final Class<?> expectedType,
100 @Nullable final Class<?> actualType) {
101 final String expected = expectedType != null ? expectedType.getName() : NO_TYPE_PLACEHOLDER;
102 final String actual = actualType != null ? actualType.getName() : NO_TYPE_PLACEHOLDER;
103 return String.format(MESSAGE_WITH_NAME_AND_TYPES, argumentName, expected, actual);
104 }
105
106 /**
107 * Constructs an {@code IllegalInstanceOfArgumentException} with the default message
108 * {@link IllegalInstanceOfArgumentException#DEFAULT_MESSAGE}.
109 */
110 public IllegalInstanceOfArgumentException() {
111 super(DEFAULT_MESSAGE);
112 }
113
114 /**
115 * Constructs an {@code IllegalInstanceOfArgumentException} with the message
116 * {@link IllegalInstanceOfArgumentException#MESSAGE_WITH_NAME_AND_TYPES} including the given name of the argument
117 * as string representation.
118 *
119 * @param argumentName
120 * the name of the passed argument
121 * @param expectedType
122 * the expected class of the given argument
123 * @param actualType
124 * the actual class of the given argument
125 */
126 public IllegalInstanceOfArgumentException(@Nullable final String argumentName, @Nullable final Class<?> expectedType,
127 @Nullable final Class<?> actualType) {
128 super(determineMessage(argumentName, expectedType, actualType));
129 }
130
131 /**
132 * Constructs a new exception with the default message {@link IllegalInstanceOfArgumentException#DEFAULT_MESSAGE}.
133 *
134 * @param cause
135 * the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). (A
136 * {@code null} value is permitted, and indicates that the cause is nonexistent or unknown.)
137 */
138 public IllegalInstanceOfArgumentException(@Nullable final Throwable cause) {
139 super(DEFAULT_MESSAGE, cause);
140 }
141
142 }