1 /* 2 * Copyright 2021 Google LLC 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 * https://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.google.android.enterprise.connectedapps.processor.containers; 17 18 import com.google.android.enterprise.connectedapps.annotations.CustomFutureWrapper; 19 import com.google.auto.value.AutoValue; 20 import com.squareup.javapoet.ClassName; 21 import java.util.ArrayList; 22 import java.util.Collection; 23 import javax.lang.model.element.TypeElement; 24 import javax.lang.model.type.TypeMirror; 25 26 /** Information about future wrapper. */ 27 @AutoValue 28 public abstract class FutureWrapper { 29 30 /** The type of the Wrapper. This controls how supporting code is generated. */ 31 public enum WrapperType { 32 DEFAULT, // Copied from a resource 33 CUSTOM // Included in classpath 34 } 35 36 public static final String FUTURE_WRAPPER_PACKAGE = 37 "com.google.android.enterprise.connectedapps.futurewrappers"; 38 wrappedType()39 public abstract TypeMirror wrappedType(); 40 defaultWrapperClassName()41 public abstract ClassName defaultWrapperClassName(); 42 wrapperClassName()43 public abstract ClassName wrapperClassName(); 44 wrapperType()45 public abstract WrapperType wrapperType(); 46 create( TypeMirror wrappedType, ClassName defaultWrapperClassName, WrapperType wrapperType)47 private static FutureWrapper create( 48 TypeMirror wrappedType, ClassName defaultWrapperClassName, WrapperType wrapperType) { 49 return create(wrappedType, defaultWrapperClassName, defaultWrapperClassName, wrapperType); 50 } 51 create( TypeMirror wrappedType, ClassName defaultWrapperClassName, ClassName wrapperClassName, WrapperType wrapperType)52 public static FutureWrapper create( 53 TypeMirror wrappedType, 54 ClassName defaultWrapperClassName, 55 ClassName wrapperClassName, 56 WrapperType wrapperType) { 57 return new AutoValue_FutureWrapper( 58 wrappedType, defaultWrapperClassName, wrapperClassName, wrapperType); 59 } 60 createGlobalFutureWrappers(Context context)61 public static Collection<FutureWrapper> createGlobalFutureWrappers(Context context) { 62 Collection<FutureWrapper> wrappers = new ArrayList<>(); 63 64 addDefaultFutureWrappers(context, wrappers); 65 66 return wrappers; 67 } 68 addDefaultFutureWrappers( Context context, Collection<FutureWrapper> wrappers)69 private static void addDefaultFutureWrappers( 70 Context context, Collection<FutureWrapper> wrappers) { 71 tryAddWrapper( 72 context, 73 wrappers, 74 "com.google.common.util.concurrent.ListenableFuture", 75 ClassName.get(FUTURE_WRAPPER_PACKAGE, "ListenableFutureWrapper"), 76 WrapperType.DEFAULT); 77 } 78 createCustomFutureWrappers( Context context, Collection<TypeElement> customFutureWrappers)79 public static Collection<FutureWrapper> createCustomFutureWrappers( 80 Context context, Collection<TypeElement> customFutureWrappers) { 81 Collection<FutureWrapper> wrappers = new ArrayList<>(); 82 83 addCustomFutureWrappers(context, wrappers, customFutureWrappers); 84 85 return wrappers; 86 } 87 addCustomFutureWrappers( Context context, Collection<FutureWrapper> wrappers, Collection<TypeElement> customFutureWrappers)88 private static void addCustomFutureWrappers( 89 Context context, 90 Collection<FutureWrapper> wrappers, 91 Collection<TypeElement> customFutureWrappers) { 92 for (TypeElement customFutureWrapper : customFutureWrappers) { 93 addCustomFutureWrapper(context, wrappers, customFutureWrapper); 94 } 95 } 96 addCustomFutureWrapper( Context context, Collection<FutureWrapper> wrappers, TypeElement customFutureWrapper)97 private static void addCustomFutureWrapper( 98 Context context, Collection<FutureWrapper> wrappers, TypeElement customFutureWrapper) { 99 CustomFutureWrapper customFutureWrapperAnnotation = 100 customFutureWrapper.getAnnotation(CustomFutureWrapper.class); 101 102 if (customFutureWrapperAnnotation == null) { 103 // This will be dealt with as part of early validation 104 return; 105 } 106 107 tryAddWrapper( 108 context, 109 wrappers, 110 FutureWrapperAnnotationInfo.extractFromFutureWrapperAnnotation( 111 context, customFutureWrapperAnnotation) 112 .originalType() 113 .toString(), 114 ClassName.get(customFutureWrapper), 115 WrapperType.CUSTOM); 116 } 117 tryAddWrapper( Context context, Collection<FutureWrapper> wrappers, String typeQualifiedName, ClassName wrapperClassName, WrapperType wrapperType)118 private static void tryAddWrapper( 119 Context context, 120 Collection<FutureWrapper> wrappers, 121 String typeQualifiedName, 122 ClassName wrapperClassName, 123 WrapperType wrapperType) { 124 TypeElement typeElement = context.elements().getTypeElement(typeQualifiedName); 125 126 if (typeElement == null) { 127 // The type isn't supported at compile-time - so won't be included in this app 128 return; 129 } 130 131 wrappers.add(FutureWrapper.create(typeElement.asType(), wrapperClassName, wrapperType)); 132 } 133 } 134