1 /* 2 * Copyright (C) 2019 The Android Open Source Project 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 com.android.car.internal.util; 17 18 import android.annotation.AppIdInt; 19 import android.annotation.ColorInt; 20 import android.annotation.FloatRange; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Size; 24 import android.annotation.UserIdInt; 25 import android.car.builtin.util.ValidationHelper; 26 27 import java.lang.annotation.Annotation; 28 29 /** 30 * Validations for common annotations, e.g. {@link IntRange}, {@link UserIdInt}, etc. 31 * 32 * For usability from generated {@link DataClass} code, all validations are overloads of 33 * {@link #validate} with the following shape: 34 * {@code 35 * <A extends Annotation> void validate( 36 * Class<A> cls, A ignored, Object value[, (String, Object)... annotationParams]) 37 * } 38 * The ignored {@link Annotation} parameter is used to differentiate between overloads that would 39 * otherwise have the same jvm signature. It's usually null at runtime. 40 */ 41 public final class AnnotationValidations { AnnotationValidations()42 private AnnotationValidations() { 43 } 44 45 /** Check class javadoc. */ validate(Class<UserIdInt> annotation, UserIdInt ignored, int value)46 public static void validate(Class<UserIdInt> annotation, UserIdInt ignored, int value) { 47 if (!ValidationHelper.isUserIdValid(value)) { 48 invalid(annotation, value); 49 } 50 } 51 52 /** Check class javadoc. */ validate(Class<AppIdInt> annotation, AppIdInt ignored, int value)53 public static void validate(Class<AppIdInt> annotation, AppIdInt ignored, int value) { 54 if (!ValidationHelper.isAppIdValid(value)) { 55 invalid(annotation, value); 56 } 57 } 58 59 /** Check class javadoc. */ validate(Class<IntRange> annotation, IntRange ignored, int value, String paramName1, long param1, String paramName2, long param2)60 public static void validate(Class<IntRange> annotation, IntRange ignored, int value, 61 String paramName1, long param1, String paramName2, long param2) { 62 validate(annotation, ignored, value, paramName1, param1); 63 validate(annotation, ignored, value, paramName2, param2); 64 } 65 66 /** Check class javadoc. */ validate(Class<IntRange> annotation, IntRange ignored, int value, String paramName, long param)67 public static void validate(Class<IntRange> annotation, IntRange ignored, int value, 68 String paramName, long param) { 69 switch (paramName) { 70 case "from": 71 if (value < param) { 72 invalid(annotation, value, paramName, param); 73 } 74 break; 75 case "to": 76 if (value > param) { 77 invalid(annotation, value, paramName, param); 78 } 79 break; 80 default: 81 break; 82 } 83 } 84 85 /** 86 * Validate a long value with two parameters. 87 */ validate(Class<IntRange> annotation, IntRange ignored, long value, String paramName1, long param1, String paramName2, long param2)88 public static void validate(Class<IntRange> annotation, IntRange ignored, long value, 89 String paramName1, long param1, String paramName2, long param2) { 90 validate(annotation, ignored, value, paramName1, param1); 91 validate(annotation, ignored, value, paramName2, param2); 92 } 93 94 /** 95 * Validate a long value with one parameter. 96 */ validate(Class<IntRange> annotation, IntRange ignored, long value, String paramName, long param)97 public static void validate(Class<IntRange> annotation, IntRange ignored, long value, 98 String paramName, long param) { 99 switch (paramName) { 100 case "from": 101 if (value < param) { 102 invalid(annotation, value, paramName, param); 103 } 104 break; 105 case "to": 106 if (value > param) { 107 invalid(annotation, value, paramName, param); 108 } 109 break; 110 default: 111 break; 112 } 113 } 114 115 /** Check class javadoc. */ validate(Class<FloatRange> annotation, FloatRange ignored, float value, String paramName1, float param1, String paramName2, float param2)116 public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value, 117 String paramName1, float param1, String paramName2, float param2) { 118 validate(annotation, ignored, value, paramName1, param1); 119 validate(annotation, ignored, value, paramName2, param2); 120 } 121 122 /** Check class javadoc. */ validate(Class<FloatRange> annotation, FloatRange ignored, float value, String paramName, float param)123 public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value, 124 String paramName, float param) { 125 switch (paramName) { 126 case "from": 127 if (value < param) invalid(annotation, value, paramName, param); 128 break; 129 case "to": 130 if (value > param) invalid(annotation, value, paramName, param); 131 break; 132 default: 133 break; 134 } 135 } 136 137 /** Check class javadoc. */ validate(Class<NonNull> annotation, NonNull ignored, Object value)138 public static void validate(Class<NonNull> annotation, NonNull ignored, Object value) { 139 if (value == null) { 140 throw new NullPointerException(); 141 } 142 } 143 144 /** Check class javadoc. */ validate(Class<Size> annotation, Size ignored, int value, String paramName1, int param1, String paramName2, int param2)145 public static void validate(Class<Size> annotation, Size ignored, int value, 146 String paramName1, int param1, String paramName2, int param2) { 147 validate(annotation, ignored, value, paramName1, param1); 148 validate(annotation, ignored, value, paramName2, param2); 149 } 150 151 /** Check class javadoc. */ validate(Class<Size> annotation, Size ignored, int value, String paramName, int param)152 public static void validate(Class<Size> annotation, Size ignored, int value, 153 String paramName, int param) { 154 switch (paramName) { 155 case "value": { 156 if (param != -1 && value != param) invalid(annotation, value, paramName, param); 157 } 158 break; 159 case "min": { 160 if (value < param) invalid(annotation, value, paramName, param); 161 } 162 break; 163 case "max": { 164 if (value > param) invalid(annotation, value, paramName, param); 165 } 166 break; 167 case "multiple": { 168 if (value % param != 0) invalid(annotation, value, paramName, param); 169 } 170 break; 171 default: 172 break; 173 } 174 } 175 176 /** @deprecated Use other versions. */ 177 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, Object value, Object... params)178 public static void validate(Class<? extends Annotation> annotation, 179 Annotation ignored, Object value, Object... params) { 180 } 181 182 /** @deprecated Use other versions. */ 183 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, Object value)184 public static void validate(Class<? extends Annotation> annotation, 185 Annotation ignored, Object value) { 186 } 187 188 /** @deprecated Use other versions. */ 189 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, int value, Object... params)190 public static void validate(Class<? extends Annotation> annotation, 191 Annotation ignored, int value, Object... params) { 192 } 193 194 /** Check class javadoc. */ validate(Class<? extends Annotation> annotation, Annotation ignored, int value)195 public static void validate(Class<? extends Annotation> annotation, 196 Annotation ignored, int value) { 197 if (("android.annotation".equals(annotation.getPackageName()) 198 && annotation.getSimpleName().endsWith("Res")) 199 || ColorInt.class.equals(annotation)) { 200 if (value < 0) { 201 invalid(annotation, value); 202 } 203 } 204 } 205 206 /** Check class javadoc. */ validate(Class<? extends Annotation> annotation, Annotation ignored, long value)207 public static void validate(Class<? extends Annotation> annotation, 208 Annotation ignored, long value) { 209 if ("android.annotation".equals(annotation.getPackageName()) 210 && annotation.getSimpleName().endsWith("Long")) { 211 if (value < 0L) { 212 invalid(annotation, value); 213 } 214 } 215 } 216 invalid(Class<? extends Annotation> annotation, Object value)217 private static void invalid(Class<? extends Annotation> annotation, Object value) { 218 invalid("@" + annotation.getSimpleName(), value); 219 } 220 invalid(Class<? extends Annotation> annotation, Object value, String paramName, Object param)221 private static void invalid(Class<? extends Annotation> annotation, Object value, 222 String paramName, Object param) { 223 String paramPrefix = "value".equals(paramName) ? "" : paramName + " = "; 224 invalid("@" + annotation.getSimpleName() + "(" + paramPrefix + param + ")", value); 225 } 226 invalid(String valueKind, Object value)227 private static void invalid(String valueKind, Object value) { 228 throw new IllegalStateException("Invalid " + valueKind + ": " + value); 229 } 230 } 231