com.apollographql.apollo.compiler.FragmentsResponseMapperBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-android-sdk-appsync-compiler Show documentation
Show all versions of aws-android-sdk-appsync-compiler Show documentation
AWS AppSync Implementation for the Gradle plugin
The newest version!
/**
* Copyright 2018-2019 Amazon.com,
* Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.apollographql.apollo.compiler
import com.apollographql.apollo.api.FragmentResponseFieldMapper
import com.apollographql.apollo.api.ResponseReader
import com.apollographql.apollo.compiler.ir.CodeGenerationContext
import com.apollographql.apollo.compiler.ir.Fragment
import com.squareup.javapoet.*
import javax.annotation.Nonnull
import javax.lang.model.element.Modifier
/**
* Responsible for [Fragments.Mapper] class generation
*
* Example of generated class:
*
* ```
* public static final class Mapper implements FragmentResponseFieldMapper {
* final HeroDetails.Mapper heroDetailsFieldMapper = new HeroDetails.Mapper();
*
* @Override
* public Fragments map(ResponseReader reader, @Nonnull String conditionalType) {
* HeroDetails heroDetails = null;
* if (conditionalType.equals(HeroDetails.TYPE_CONDITION)) {
* heroDetails = heroDetailsFieldMapper.map(reader);
* }
* return new Fragments(heroDetails);
* }
* }
*
*```
*/
class FragmentsResponseMapperBuilder(
val fragmentFields: List,
val context: CodeGenerationContext
) {
fun build(): TypeSpec {
return TypeSpec.classBuilder(Util.RESPONSE_FIELD_MAPPER_TYPE_NAME)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.addSuperinterface(RESPONSE_FIELD_MAPPER_TYPE)
.addFields(mapperFields(fragmentFields))
.addMethod(mapMethod(fragmentFields))
.build()
}
private fun mapMethod(fragmentFields: List) =
MethodSpec.methodBuilder("map")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override::class.java)
.addParameter(READER_PARAM)
.addParameter(CONDITIONAL_TYPE_PARAM)
.returns(SchemaTypeSpecBuilder.FRAGMENTS_FIELD.type)
.addCode(mapMethodCode(fragmentFields))
.build()
private fun mapMethodCode(fragmentFields: List) =
CodeBlock.builder()
.add(initFragmentsCode(fragmentFields))
.add(createFragmentsCode(fragmentFields))
.add(");\n")
.build()
private fun initFragmentsCode(fragmentFields: List) =
CodeBlock.builder()
.add(fragmentFields
.fold(CodeBlock.builder()) { builder, field ->
builder.addStatement("\$T \$N = null", field.type.unwrapOptionalType(withoutAnnotations = true), field)
}
.build())
.add(fragmentFields
.fold(CodeBlock.builder()) { builder, field -> builder.add(initFragmentCode(field)) }
.build())
.build()
private fun initFragmentCode(fragmentField: FieldSpec): CodeBlock {
val fieldClass = fragmentField.type.unwrapOptionalType(withoutAnnotations = true) as ClassName
return CodeBlock.builder()
.beginControlFlow("if (\$T.\$L.contains(\$L))", fieldClass, Fragment.POSSIBLE_TYPES_VAR, CONDITIONAL_TYPE_VAR)
.addStatement("\$N = \$L.map(\$L)", fragmentField, fieldClass.mapperFieldName(), READER_VAR)
.endControlFlow()
.build()
}
private fun createFragmentsCode(fragmentFields: List) =
CodeBlock.builder()
.add("return new \$L(", SchemaTypeSpecBuilder.FRAGMENTS_FIELD.type.withoutAnnotations())
.add(fragmentFields
.mapIndexed { i, fieldSpec ->
if (fieldSpec.type.isNullable()) {
CodeBlock.of("\$L\$L", if (i > 0) ", " else "", fieldSpec.name)
} else {
CodeBlock.of("\$L\$T.checkNotNull(\$L, \$S)", if (i > 0) ", " else "", ClassNames.API_UTILS,
fieldSpec.name, "${fieldSpec.name} == null")
}
}
.fold(CodeBlock.builder(), CodeBlock.Builder::add)
.build())
.build()
private fun mapperFields(fragments: List) =
fragments
.map { it.type.unwrapOptionalType(withoutAnnotations = true) as ClassName }
.map {
val mapperClassName = ClassName.get(context.fragmentsPackage, it.simpleName(),
Util.RESPONSE_FIELD_MAPPER_TYPE_NAME)
FieldSpec.builder(mapperClassName, it.mapperFieldName(), Modifier.FINAL)
.initializer(CodeBlock.of("new \$T()", mapperClassName))
.build()
}
companion object {
private val API_RESPONSE_FIELD_MAPPER_TYPE = ClassName.get(
FragmentResponseFieldMapper::class.java)
private val RESPONSE_FIELD_MAPPER_TYPE = ParameterizedTypeName.get(API_RESPONSE_FIELD_MAPPER_TYPE,
SchemaTypeSpecBuilder.FRAGMENTS_FIELD.type.withoutAnnotations())
private val CONDITIONAL_TYPE_VAR = "conditionalType"
private val CONDITIONAL_TYPE_PARAM = ParameterSpec.builder(String::class.java, CONDITIONAL_TYPE_VAR)
.addAnnotation(Nonnull::class.java).build()
private val READER_VAR = "reader"
private val READER_PARAM = ParameterSpec.builder(ResponseReader::class.java, READER_VAR).build()
}
}