private static final Joiner argumentJoiner = Joiner.on(", ");
void writeFactory(final FactoryDescriptor descriptor)
throws IOException {
JavaFileObject sourceFile = filer.createSourceFile(descriptor.name());
JavaWriter writer = new JavaWriter(sourceFile.openWriter());
String packageName = getPackage(descriptor.name()).toString();
writer.emitPackage(packageName)
.emitImports("javax.annotation.Generated");
writer.emitImports("javax.inject.Inject");
if (!descriptor.providerNames().isEmpty()) {
writer.emitImports("javax.inject.Provider");
}
for (String implementingType : descriptor.implementingTypes()) {
String implementingPackageName = getPackage(implementingType).toString();
if (!"java.lang".equals(implementingPackageName)
&& !packageName.equals(implementingPackageName)) {
writer.emitImports(implementingType);
}
}
String[] implementedClasses = FluentIterable.from(descriptor.implementingTypes())
.transform(new Function<String, String>() {
@Override public String apply(String implemetingClass) {
return getSimpleName(implemetingClass).toString();
}
})
.toSortedSet(Ordering.natural())
.toArray(new String[0]);
String factoryName = getSimpleName(descriptor.name()).toString();
writer.emitAnnotation(Generated.class,
ImmutableMap.of("value", "\"" + AutoFactoryProcessor.class.getName() + "\""));
EnumSet<Modifier> modifiers = EnumSet.of(FINAL);
if (descriptor.publicType()) {
modifiers.add(PUBLIC);
}
writer.beginType(factoryName, "class", modifiers,
Object.class.getName().equals(descriptor.extendingType())
? null : descriptor.extendingType(),
implementedClasses);
ImmutableList.Builder<String> constructorTokens = ImmutableList.builder();
for (Entry<Key, String> entry : descriptor.providerNames().entrySet()) {
Key key = entry.getKey();
String providerName = entry.getValue();
writer.emitField("Provider<" + key.getType() + ">", providerName, EnumSet.of(PRIVATE, FINAL));
Optional<String> qualifier = key.getQualifier();
String qualifierPrefix = qualifier.isPresent() ? "@" + qualifier.get() + " " : "";
constructorTokens.add(qualifierPrefix + "Provider<" + key.getType() + ">").add(providerName);
}
writer.emitAnnotation("Inject");
writer.beginMethod(null, factoryName,
descriptor.publicType() ? EnumSet.of(PUBLIC) : EnumSet.noneOf(Modifier.class),
constructorTokens.build().toArray(new String[0]));
for (String providerName : descriptor.providerNames().values()) {
writer.emitStatement("this.%1$s = %1$s", providerName);
}
writer.endMethod();
for (final FactoryMethodDescriptor methodDescriptor : descriptor.methodDescriptors()) {
writer.beginMethod(methodDescriptor.returnType(), methodDescriptor.name(),
methodDescriptor.publicMethod() ? EnumSet.of(PUBLIC) : EnumSet.noneOf(Modifier.class),
parameterTokens(methodDescriptor.passedParameters()));
FluentIterable<String> creationParameterNames =
FluentIterable.from(methodDescriptor.creationParameters())
.transform(new Function<Parameter, String>() {
@Override public String apply(Parameter parameter) {
return methodDescriptor.passedParameters().contains(parameter)
? parameter.name()
: descriptor.providerNames().get(parameter.asKey()) + ".get()";
}
});
writer.emitStatement("return new %s(%s)", writer.compressType(methodDescriptor.returnType()),
argumentJoiner.join(creationParameterNames));
writer.endMethod();
}
for (ImplemetationMethodDescriptor methodDescriptor
: descriptor.implementationMethodDescriptors()) {
writer.emitAnnotation(Override.class);
writer.beginMethod(methodDescriptor.returnType(), methodDescriptor.name(),
methodDescriptor.publicMethod() ? EnumSet.of(PUBLIC) : EnumSet.noneOf(Modifier.class),
parameterTokens(methodDescriptor.passedParameters()));
FluentIterable<String> creationParameterNames =
FluentIterable.from(methodDescriptor.passedParameters())
.transform(new Function<Parameter, String>() {
@Override public String apply(Parameter parameter) {
return parameter.name();
}
});
writer.emitStatement("return create(%s)", argumentJoiner.join(creationParameterNames));
writer.endMethod();
}
writer.endType();
writer.close();
}