1/*
2 * Copyright (C) 2015 Google, Inc.
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 */
16package dagger.internal.codegen;
17
18import com.google.common.base.Optional;
19import com.google.common.collect.ImmutableSet;
20import dagger.Module;
21import dagger.Provides;
22import dagger.internal.codegen.writer.ClassName;
23import dagger.internal.codegen.writer.ClassWriter;
24import dagger.internal.codegen.writer.FieldWriter;
25import dagger.internal.codegen.writer.JavaWriter;
26import dagger.internal.codegen.writer.MethodWriter;
27import dagger.internal.codegen.writer.ParameterizedTypeName;
28import dagger.internal.codegen.writer.TypeName;
29import dagger.producers.monitoring.ProductionComponentMonitor;
30import dagger.producers.monitoring.internal.MonitorCache;
31
32import java.util.Set;
33import javax.annotation.Generated;
34import javax.annotation.processing.Filer;
35import javax.inject.Provider;
36import javax.lang.model.element.Element;
37import javax.lang.model.element.TypeElement;
38
39import static javax.lang.model.element.Modifier.PRIVATE;
40import static javax.lang.model.element.Modifier.STATIC;
41import static javax.lang.model.element.Modifier.FINAL;
42
43/** Generates a monitoring module for use with production components. */
44final class MonitoringModuleGenerator extends SourceFileGenerator<TypeElement> {
45  private static final TypeName SET_OF_FACTORIES =
46      ParameterizedTypeName.create(
47          Set.class, ClassName.fromClass(ProductionComponentMonitor.Factory.class));
48
49  MonitoringModuleGenerator(Filer filer) {
50    super(filer);
51  }
52
53  @Override
54  ClassName nameGeneratedType(TypeElement componentElement) {
55    return SourceFiles.generatedMonitoringModuleName(componentElement);
56  }
57
58  @Override
59  Iterable<? extends Element> getOriginatingElements(TypeElement componentElement) {
60    return ImmutableSet.of(componentElement);
61  }
62
63  @Override
64  Optional<? extends Element> getElementForErrorReporting(TypeElement componentElement) {
65    return Optional.of(componentElement);
66  }
67
68  @Override
69  ImmutableSet<JavaWriter> write(ClassName generatedTypeName, TypeElement componentElement) {
70    JavaWriter writer = JavaWriter.inPackage(generatedTypeName.packageName());
71    ClassWriter classWriter = writer.addClass(generatedTypeName.simpleName());
72    classWriter.annotate(Generated.class).setValue(ComponentProcessor.class.getName());
73    classWriter.annotate(Module.class);
74    classWriter.addModifiers(FINAL);
75
76    // TODO(beder): Replace this default set binding with EmptyCollections when it exists.
77    MethodWriter emptySetBindingMethod =
78        classWriter.addMethod(SET_OF_FACTORIES, "defaultSetOfFactories");
79    emptySetBindingMethod.addModifiers(STATIC);
80    emptySetBindingMethod.annotate(Provides.class).setMember("type", Provides.Type.SET_VALUES);
81    emptySetBindingMethod
82        .body()
83        .addSnippet("return %s.of();", ClassName.fromClass(ImmutableSet.class));
84
85    FieldWriter providerField = classWriter.addField(MonitorCache.class, "monitorCache");
86    providerField.addModifiers(PRIVATE, FINAL);
87    providerField.setInitializer("new %s()", ClassName.fromClass(MonitorCache.class));
88    MethodWriter monitorMethod = classWriter.addMethod(ProductionComponentMonitor.class, "monitor");
89    monitorMethod.annotate(Provides.class);
90    monitorMethod.addParameter(
91        ParameterizedTypeName.create(Provider.class, ClassName.fromTypeElement(componentElement)),
92        "component");
93    monitorMethod.addParameter(
94        ParameterizedTypeName.create(Provider.class, SET_OF_FACTORIES), "factories");
95    monitorMethod.body().addSnippet("return monitorCache.monitor(component, factories);");
96
97    return ImmutableSet.of(writer);
98  }
99}
100