001package ball.lang.reflect; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: JavaLangReflectMethods.java 5895 2020-05-08 15:55:11Z 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 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: 5895 $ 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 String string = 168 modifiers(modifiers) 169 + " " + type(method.getGenericReturnType()) 170 + " " + method.getName() 171 + parameters(method.getParameters()) 172 + " " + exceptions(method.getGenericExceptionTypes()); 173 174 return string.trim(); 175 } 176 177 /** 178 * Method to generate a {@link Constructor} or {@link Method} parameter 179 * declaration. 180 * 181 * @param parameters The target {@link Parameter} array. 182 * 183 * @return {@link String} 184 */ 185 default String parameters(Parameter[] parameters) { 186 return Stream.of(parameters) 187 .map(t -> declaration(t)) 188 .collect(joining(", ", "(", ")")); 189 } 190 191 /** 192 * Method to generate a {@link Constructor} or {@link Method} thrown 193 * exception list. 194 * 195 * @param exceptions The target {@link Type} array. 196 * 197 * @return {@link String} 198 */ 199 default String exceptions(Type[] exceptions) { 200 String string = ""; 201 202 if (exceptions != null && exceptions.length > 0) { 203 string = 204 Stream.of(exceptions) 205 .map(t -> type(t)) 206 .collect(joining(", ", "throws ", "")); 207 } 208 209 return string; 210 } 211 212 /** 213 * Method to generate a {@link Parameter} declaration. 214 * 215 * @param parameter The target {@link Parameter}. 216 * 217 * @return {@link String} 218 */ 219 default String declaration(Parameter parameter) { 220 String string = 221 modifiers(parameter.getModifiers()) 222 + " " + type(parameter.getParameterizedType()) 223 + " " + parameter.getName(); 224 225 return string.trim(); 226 } 227 228 /** 229 * Method to generate modifiers for {@code declaration()} methods. 230 * 231 * @param modifiers See {@link Modifier}. 232 * 233 * @return {@link String} 234 */ 235 default String modifiers(int modifiers) { 236 return java.lang.reflect.Modifier.toString(modifiers); 237 } 238 239 /** 240 * Method to generate types for {@code declaration()} methods. 241 * 242 * @param type The {@link Type}. 243 * 244 * @return {@link String} 245 */ 246 default String type(Type type) { 247 String string = null; 248 249 if (type instanceof ParameterizedType) { 250 string = type((ParameterizedType) type); 251 } else if (type instanceof Class<?>) { 252 string = ((Class<?>) type).getSimpleName(); 253 } else { 254 string = type.getTypeName(); 255 } 256 257 return string; 258 } 259 260 /** 261 * Method to generate types for {@code declaration()} methods. 262 * 263 * @param type The {@link ParameterizedType}. 264 * 265 * @return {@link String} 266 */ 267 default String type(ParameterizedType type) { 268 return Stream.of(type.getActualTypeArguments()) 269 .map(t -> type(t)) 270 .collect(joining(",", type(type.getRawType()) + "<", ">")); 271 } 272}