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 java.lang.annotation.Annotation; 19 20 import javax.annotation.Nonnull; 21 import javax.annotation.Nullable; 22 23 import net.sf.qualitycheck.ArgumentsChecked; 24 import net.sf.qualitycheck.Throws; 25 26 /** 27 * Thrown to indicate that a method has been passed with a class that does not have a required annotation. 28 * 29 * @author André Rouél 30 * @author Dominik Seichter 31 */ 32 public class IllegalMissingAnnotationException extends RuntimeException { 33 34 private static final long serialVersionUID = -8428891146741574807L; 35 36 /** 37 * Default message to indicate that the a given class must have an annotation. 38 */ 39 protected static final String DEFAULT_MESSAGE = "Annotation is required on the passed class."; 40 41 /** 42 * Message to indicate that the the given class must be annotated with annotation '%s'. 43 */ 44 protected static final String MESSAGE_WITH_ANNOTATION = "Class must have annotation '%s'."; 45 46 /** 47 * Message to indicate that the the given class with <em>name</em> must be annotated with annotation '%s'. 48 */ 49 protected static final String MESSAGE_WITH_ANNOTATION_AND_CLASS = "Class '%s' must have annotation '%s'."; 50 51 /** 52 * Annotation to search on a class 53 */ 54 @Nullable 55 private final Class<? extends Annotation> annotation; 56 57 /** 58 * Class to check for an annotation 59 */ 60 @Nullable 61 private final Class<?> clazz; 62 63 /** 64 * Returns the formatted string {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION} with the given 65 * {@code annotation}. 66 * 67 * @param annotation 68 * the name of the required annotation 69 * @return a formatted string of message with the given argument name 70 */ 71 @ArgumentsChecked 72 @Throws(IllegalNullArgumentException.class) 73 private static String format(@Nonnull final Class<? extends Annotation> annotation) { 74 if (annotation == null) { 75 throw new IllegalNullArgumentException("annotation"); 76 } 77 return String.format(MESSAGE_WITH_ANNOTATION, annotation.getName()); 78 } 79 80 /** 81 * Returns the formatted string {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION_AND_CLASS} with the 82 * given {@code annotation} and {@code clazz}. 83 * 84 * @param annotation 85 * the required annotation 86 * @param clazz 87 * the name of the class which does not have the required annotation 88 * @return a formatted string of message with the given argument name 89 */ 90 @ArgumentsChecked 91 @Throws(IllegalNullArgumentException.class) 92 private static String format(@Nonnull final Class<? extends Annotation> annotation, @Nullable final Class<?> clazz) { 93 if (annotation == null) { 94 throw new IllegalNullArgumentException("annotation"); 95 } 96 97 if (clazz != null) { 98 return String.format(MESSAGE_WITH_ANNOTATION_AND_CLASS, clazz.getName(), annotation.getName()); 99 } else { 100 return format(annotation); 101 } 102 } 103 104 /** 105 * Constructs an {@code IllegalMissingAnnotationException} with the default message 106 * {@link IllegalMissingAnnotationException#DEFAULT_MESSAGE}. 107 */ 108 public IllegalMissingAnnotationException() { 109 super(DEFAULT_MESSAGE); 110 this.annotation = null; 111 this.clazz = null; 112 } 113 114 /** 115 * Constructs an {@code IllegalMissingAnnotationException} with the message 116 * {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION} including the name of the missing annotation. 117 * 118 * @param annotation 119 * the required annotation 120 */ 121 public IllegalMissingAnnotationException(@Nonnull final Class<? extends Annotation> annotation) { 122 super(format(annotation)); 123 this.annotation = annotation; 124 this.clazz = null; 125 } 126 127 /** 128 * Constructs a new exception with the message {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION} 129 * including the name of the missing annotation. 130 * 131 * @param annotation 132 * the required annotation 133 * @param cause 134 * the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). (A 135 * {@code null} value is permitted, and indicates that the cause is nonexistent or unknown.) 136 */ 137 public IllegalMissingAnnotationException(@Nonnull final Class<? extends Annotation> annotation, @Nullable final Throwable cause) { 138 super(format(annotation), cause); 139 this.annotation = annotation; 140 this.clazz = null; 141 } 142 143 /** 144 * Constructs an {@code IllegalMissingAnnotationException} with the message 145 * {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION} including the name of the missing annotation. 146 * 147 * @param annotation 148 * the required annotation 149 * @param clazz 150 * the name of the class which does not have the required annotation 151 */ 152 public IllegalMissingAnnotationException(@Nonnull final Class<? extends Annotation> annotation, @Nullable final Class<?> clazz) { 153 super(format(annotation, clazz)); 154 this.annotation = annotation; 155 this.clazz = clazz; 156 } 157 158 /** 159 * Constructs a new exception with the message {@link IllegalMissingAnnotationException#MESSAGE_WITH_ANNOTATION} 160 * including the name of the missing annotation. 161 * 162 * @param annotation 163 * the required annotation 164 * @param clazz 165 * the name of the class which does not have the required annotation 166 * @param cause 167 * the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). (A 168 * {@code null} value is permitted, and indicates that the cause is nonexistent or unknown.) 169 */ 170 public IllegalMissingAnnotationException(@Nonnull final Class<? extends Annotation> annotation, @Nullable final Class<?> clazz, 171 @Nullable final Throwable cause) { 172 super(format(annotation, clazz), cause); 173 this.annotation = annotation; 174 this.clazz = clazz; 175 } 176 177 /** 178 * Constructs a new exception with the default message {@link IllegalMissingAnnotationException#DEFAULT_MESSAGE}. 179 * 180 * @param cause 181 * the cause (which is saved for later retrieval by the {@link Throwable#getCause()} method). (A 182 * {@code null} value is permitted, and indicates that the cause is nonexistent or unknown.) 183 */ 184 public IllegalMissingAnnotationException(@Nullable final Throwable cause) { 185 super(DEFAULT_MESSAGE, cause); 186 this.annotation = null; 187 this.clazz = null; 188 } 189 190 /** 191 * Gives access to the required annotation. 192 * 193 * @return the annotation which was expected on a class and was not found 194 */ 195 public Class<? extends Annotation> getMissingAnnotation() { 196 return annotation; 197 } 198 199 /** 200 * Gives access to the class which does not have a required annotation. 201 * 202 * @return the class which caused the exception by not having a required annotation 203 */ 204 public Class<?> getClassWithoutAnnotation() { 205 return this.clazz; 206 } 207 208 }