001package ball.annotation.processing; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: ConstantValueMustConvertToProcessor.java 6106 2020-06-03 19:39:35Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/annotation/processing/ConstantValueMustConvertToProcessor.java $ 007 * %% 008 * Copyright (C) 2008 - 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 ball.annotation.ConstantValueMustConvertTo; 024import ball.annotation.ServiceProviderFor; 025import java.lang.reflect.InvocationTargetException; 026import javax.annotation.processing.Processor; 027import javax.annotation.processing.RoundEnvironment; 028import javax.lang.model.element.AnnotationMirror; 029import javax.lang.model.element.AnnotationValue; 030import javax.lang.model.element.Element; 031import javax.lang.model.element.TypeElement; 032import javax.lang.model.element.VariableElement; 033import javax.lang.model.type.TypeMirror; 034import lombok.NoArgsConstructor; 035import lombok.ToString; 036 037import static javax.tools.Diagnostic.Kind.ERROR; 038 039/** 040 * {@link Processor} implementation to verify constant initializers 041 * marked by the {@link ConstantValueMustConvertTo} can be converted to the 042 * specified type. 043 * 044 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 045 * @version $Revision: 6106 $ 046 */ 047@ServiceProviderFor({ Processor.class }) 048@For({ ConstantValueMustConvertTo.class }) 049@NoArgsConstructor @ToString 050public class ConstantValueMustConvertToProcessor extends AnnotatedProcessor { 051 @Override 052 public void process(RoundEnvironment roundEnv, 053 TypeElement annotation, Element element) { 054 super.process(roundEnv, annotation, element); 055 056 AnnotationMirror mirror = getAnnotationMirror(element, annotation); 057 AnnotationValue value = getAnnotationValue(mirror, "value"); 058 TypeElement to = 059 (TypeElement) types.asElement((TypeMirror) value.getValue()); 060 String method = 061 (String) getAnnotationValue(mirror, "method").getValue(); 062 Object from = null; 063 064 try { 065 from = ((VariableElement) element).getConstantValue(); 066 067 Class<?> type = Class.forName(to.getQualifiedName().toString()); 068 069 if (! method.isEmpty()) { 070 type.getMethod(method, from.getClass()) 071 .invoke(null, from); 072 } else { 073 type.getConstructor(from.getClass()) 074 .newInstance(from); 075 } 076 } catch (Exception exception) { 077 Throwable throwable = exception; 078 079 while (throwable instanceof InvocationTargetException) { 080 throwable = throwable.getCause(); 081 } 082 083 print(ERROR, element, 084 "Cannot convert %s to %s\n%s: %s", 085 elements.getConstantExpression(from), 086 to.getQualifiedName(), 087 throwable.getClass().getName(), throwable.getMessage()); 088 } 089 } 090}