1 /* 2 * Copyright (C) 2016 The Dagger Authors. 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 17 package dagger.internal.codegen.base; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static javax.lang.model.util.ElementFilter.methodsIn; 21 22 import com.google.auto.common.MoreTypes; 23 import com.google.common.base.Functions; 24 import com.google.common.base.Joiner; 25 import com.google.common.collect.FluentIterable; 26 import com.google.common.collect.ImmutableMap; 27 import com.google.common.collect.Maps; 28 import java.util.Map; 29 import javax.lang.model.element.AnnotationMirror; 30 import javax.lang.model.element.AnnotationValue; 31 import javax.lang.model.element.ElementKind; 32 import javax.lang.model.element.ExecutableElement; 33 import javax.lang.model.element.TypeElement; 34 import javax.lang.model.type.DeclaredType; 35 36 /** A representation of an annotation. */ 37 public final class SimpleAnnotationMirror implements AnnotationMirror { 38 private final TypeElement annotationType; 39 private final ImmutableMap<String, ? extends AnnotationValue> namedValues; 40 private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues; 41 SimpleAnnotationMirror( TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues)42 private SimpleAnnotationMirror( 43 TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) { 44 checkArgument( 45 annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE), 46 "annotationType must be an annotation: %s", 47 annotationType); 48 checkArgument( 49 FluentIterable.from(methodsIn(annotationType.getEnclosedElements())) 50 .transform(element -> element.getSimpleName().toString()) 51 .toSet() 52 .equals(namedValues.keySet()), 53 "namedValues must have values for exactly the members in %s: %s", 54 annotationType, 55 namedValues); 56 this.annotationType = annotationType; 57 this.namedValues = ImmutableMap.copyOf(namedValues); 58 this.elementValues = 59 Maps.toMap( 60 methodsIn(annotationType.getEnclosedElements()), 61 Functions.compose( 62 Functions.forMap(namedValues), element -> element.getSimpleName().toString())); 63 } 64 65 @Override getAnnotationType()66 public DeclaredType getAnnotationType() { 67 return MoreTypes.asDeclared(annotationType.asType()); 68 } 69 70 @Override getElementValues()71 public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() { 72 return elementValues; 73 } 74 75 @Override toString()76 public String toString() { 77 StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName()); 78 if (!namedValues.isEmpty()) { 79 builder 80 .append('(') 81 .append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues)) 82 .append(')'); 83 } 84 return builder.toString(); 85 } 86 87 /** 88 * An object representing an annotation instance. 89 * 90 * @param annotationType must be an annotation type with no members 91 */ of(TypeElement annotationType)92 public static AnnotationMirror of(TypeElement annotationType) { 93 return of(annotationType, ImmutableMap.<String, AnnotationValue>of()); 94 } 95 96 /** 97 * An object representing an annotation instance. 98 * 99 * @param annotationType must be an annotation type 100 * @param namedValues a value for every annotation member, including those with defaults, indexed 101 * by simple name 102 */ of( TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues)103 private static AnnotationMirror of( 104 TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) { 105 return new SimpleAnnotationMirror(annotationType, namedValues); 106 } 107 } 108