001package ball.lang.reflect; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: JavaLangReflectMethods.java 8226 2021-07-02 21:14:59Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/lang/reflect/JavaLangReflectMethods.java $ 007 * %% 008 * Copyright (C) 2020, 2021 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import java.lang.reflect.Constructor; 024import java.lang.reflect.Field; 025import java.lang.reflect.Member; 026import java.lang.reflect.Method; 027import java.lang.reflect.Parameter; 028import java.lang.reflect.ParameterizedType; 029import java.lang.reflect.Type; 030import java.util.EnumSet; 031import java.util.stream.Stream; 032import javax.lang.model.element.Modifier; 033 034import static java.util.stream.Collectors.joining; 035 036/** 037 * {@link java.lang.reflect} and {@link javax.lang.model.element} utility 038 * methods. 039 * 040 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 041 * @version $Revision: 8226 $ 042 */ 043public interface JavaLangReflectMethods { 044 045 /** 046 * Method to translate {@link Class} and {@link Member} 047 * {@link java.lang.reflect.Modifier} flags to an {@link EnumSet} of 048 * {@link Modifier}s. 049 * 050 * @param modifiers The {@code int} representing the modifiers. 051 * 052 * @return The {@link EnumSet} of {@link Modifier}s. 053 */ 054 default EnumSet<Modifier> asModifierSet(int modifiers) { 055 EnumSet<Modifier> set = EnumSet.noneOf(Modifier.class); 056 057 Stream.of(java.lang.reflect.Modifier.toString(modifiers) 058 .split("[\\p{Space}]+")) 059 .filter(t -> (! t.isEmpty())) 060 .map(String::toUpperCase) 061 .map(Modifier::valueOf) 062 .forEach(set::add); 063 064 return set; 065 } 066 067 /** 068 * See {@link #asModifierSet(int)}. 069 * 070 * @param type The {@link Class}. 071 * 072 * @return The {@link EnumSet} of {@link Modifier}s. 073 */ 074 default EnumSet<Modifier> getModifiers(Class<?> type) { 075 return asModifierSet(type.getModifiers()); 076 } 077 078 /** 079 * See {@link #asModifierSet(int)}. 080 * 081 * @param member The {@link Member}. 082 * 083 * @return The {@link EnumSet} of {@link Modifier}s. 084 */ 085 default EnumSet<Modifier> getModifiers(Member member) { 086 return asModifierSet(member.getModifiers()); 087 } 088 089 /** 090 * Dispatches call to {@link #declaration(Constructor)}, 091 * {@link #declaration(Field)}, or {@link #declaration(Method)} as 092 * appropriate. 093 * 094 * @param member The target {@link Member}. 095 * 096 * @return {@link String} 097 */ 098 default String declaration(Member member) { 099 String string = null; 100 101 if (member instanceof Constructor) { 102 string = declaration((Constructor) member); 103 } else if (member instanceof Field) { 104 string = declaration((Field) member); 105 } else if (member instanceof Method) { 106 string = declaration((Method) member); 107 } else { 108 throw new IllegalArgumentException(String.valueOf(member)); 109 } 110 111 return string; 112 } 113 114 /** 115 * Method to generate a {@link Constructor} declaration. 116 * 117 * @param constructor The target {@link Constructor}. 118 * 119 * @return {@link String} 120 */ 121 default String declaration(Constructor<?> constructor) { 122 String string = 123 modifiers(constructor.getModifiers()) 124 + " " + constructor.getName() 125 + parameters(constructor.getParameters()) 126 + " " + exceptions(constructor.getGenericExceptionTypes()); 127 128 return string.trim(); 129 } 130 131 /** 132 * Method to generate a {@link Field} declaration. 133 * 134 * @param field The target {@link Field}. 135 * 136 * @return {@link String} 137 */ 138 default String declaration(Field field) { 139 String string = 140 modifiers(field.getModifiers()) 141 + " " + type(field.getGenericType()) 142 + " " + field.getName(); 143 144 return string.trim(); 145 } 146 147 /** 148 * Method to generate a {@link Method} declaration. 149 * 150 * @param method The target {@link Method}. 151 * 152 * @return {@link String} 153 */ 154 default String declaration(Method method) { 155 return declaration(method.getModifiers(), method); 156 } 157 158 /** 159 * Method to generate a {@link Method} declaration. 160 * 161 * @param modifiers The adjusted modifiers. 162 * @param method The target {@link Method}. 163 * 164 * @return {@link String} 165 */ 166 default String declaration(int modifiers, Method method) { 167 return declaration(modifiers, method.getGenericReturnType(), method); 168 } 169 170 /** 171 * Method to generate a {@link Method} declaration. 172 * 173 * @param modifiers The adjusted modifiers. 174 * @param returnType The adjusted return {@link Type}. 175 * @param method The target {@link Method}. 176 * 177 * @return {@link String} 178 */ 179 default String declaration(int modifiers, Type returnType, Method method) { 180 return declaration(modifiers, type(returnType), method); 181 } 182 183 /** 184 * Method to generate a {@link Method} declaration. 185 * 186 * @param modifiers The adjusted modifiers. 187 * @param returnType The adjusted return {@link Type} 188 * (as a {@link String}). 189 * @param method The target {@link Method}. 190 * 191 * @return {@link String} 192 */ 193 default String declaration(int modifiers, String returnType, Method method) { 194 String string = 195 modifiers(modifiers) 196 + " " + returnType 197 + " " + method.getName() 198 + parameters(method.getParameters()) 199 + " " + exceptions(method.getGenericExceptionTypes()); 200 201 return string.trim(); 202 } 203 204 /** 205 * Method to generate a {@link Constructor} or {@link Method} parameter 206 * declaration. 207 * 208 * @param parameters The target {@link Parameter} array. 209 * 210 * @return {@link String} 211 */ 212 default String parameters(Parameter[] parameters) { 213 return Stream.of(parameters) 214 .map(t -> declaration(t)) 215 .collect(joining(", ", "(", ")")); 216 } 217 218 /** 219 * Method to generate a {@link Constructor} or {@link Method} thrown 220 * exception list. 221 * 222 * @param exceptions The target {@link Type} array. 223 * 224 * @return {@link String} 225 */ 226 default String exceptions(Type[] exceptions) { 227 String string = ""; 228 229 if (exceptions != null && exceptions.length > 0) { 230 string = 231 Stream.of(exceptions) 232 .map(t -> type(t)) 233 .collect(joining(", ", "throws ", "")); 234 } 235 236 return string; 237 } 238 239 /** 240 * Method to generate a {@link Parameter} declaration. 241 * 242 * @param parameter The target {@link Parameter}. 243 * 244 * @return {@link String} 245 */ 246 default String declaration(Parameter parameter) { 247 String string = 248 modifiers(parameter.getModifiers()) 249 + " " + type(parameter.getParameterizedType()) 250 + " " + parameter.getName(); 251 252 return string.trim(); 253 } 254 255 /** 256 * Method to generate modifiers for {@code declaration()} methods. 257 * 258 * @param modifiers See {@link Modifier}. 259 * 260 * @return {@link String} 261 */ 262 default String modifiers(int modifiers) { 263 return java.lang.reflect.Modifier.toString(modifiers); 264 } 265 266 /** 267 * Method to generate types for {@code declaration()} methods. 268 * 269 * @param type The {@link Type}. 270 * 271 * @return {@link String} 272 */ 273 default String type(Type type) { 274 String string = null; 275 276 if (type instanceof ParameterizedType) { 277 string = type((ParameterizedType) type); 278 } else if (type instanceof Class<?>) { 279 string = ((Class<?>) type).getSimpleName(); 280 } else { 281 string = type.getTypeName(); 282 } 283 284 return string; 285 } 286 287 /** 288 * Method to generate types for {@code declaration()} methods. 289 * 290 * @param type The {@link ParameterizedType}. 291 * 292 * @return {@link String} 293 */ 294 default String type(ParameterizedType type) { 295 return Stream.of(type.getActualTypeArguments()) 296 .map(t -> type(t)) 297 .collect(joining(",", type(type.getRawType()) + "<", ">")); 298 } 299}