Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.apollographql.apollo.compiler.ir.Field.kt Maven / Gradle / Ivy
/**
* Copyright 2018-2019 Amazon.com,
* Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package com.apollographql.apollo.compiler.ir
import com.apollographql.apollo.compiler.*
import com.squareup.javapoet.*
import java.util.*
import javax.lang.model.element.Modifier
import com.apollographql.apollo.compiler.ClassNames.S3Object
data class Field(
val responseName: String,
val fieldName: String,
val type: String,
val args: List>? = null,
val isConditional: Boolean = false,
val fields: List? = null,
val fragmentSpreads: List? = null,
val inlineFragments: List? = null,
val description: String? = null,
val isDeprecated: Boolean? = false,
val deprecationReason: String? = null,
val conditions: List? = null
) : CodeGenerator {
override fun toTypeSpec(context: CodeGenerationContext): TypeSpec {
val fields = if (isNonScalar()) fields!! else emptyList()
var s3ParameterCount = 0
for (field in fields) {
if (field.fieldName.equals("bucket")
|| field.fieldName.equals("key")
|| field.fieldName.equals("region")) {
s3ParameterCount += 1
}
}
var schemaTypeBuilder = SchemaTypeSpecBuilder(
typeName = formatClassName(),
schemaType = type,
fields = fields,
fragmentSpreads = fragmentSpreads ?: emptyList(),
inlineFragments = inlineFragments ?: emptyList(),
context = context
)
.build(Modifier.PUBLIC, Modifier.STATIC)
.let {
if (context.generateModelBuilder) {
it.withBuilder()
} else {
it
}
}
// if we identify the object to be S3Object type, we implement the S3ObjectInterface
if (s3ParameterCount == 3) {
schemaTypeBuilder = schemaTypeBuilder.toBuilder().addSuperinterface(S3Object).build()
}
return schemaTypeBuilder
}
fun accessorMethodSpec(context: CodeGenerationContext): MethodSpec {
return MethodSpec.methodBuilder(responseName.escapeJavaReservedWord())
.addModifiers(Modifier.PUBLIC)
.returns(toTypeName(methodResponseType(), context))
.addStatement("return this.\$L", responseName.escapeJavaReservedWord())
.let { if (description != null) it.addJavadoc("\$L\n", description) else it }
.let {
if (isDeprecated ?: false && !deprecationReason.isNullOrBlank()) {
it.addJavadoc("@deprecated \$L\n", deprecationReason)
} else {
it
}
}
.build()
}
fun fieldSpec(context: CodeGenerationContext, publicModifier: Boolean = false): FieldSpec {
return FieldSpec.builder(toTypeName(methodResponseType(), context), responseName.escapeJavaReservedWord())
.let { if (publicModifier) it.addModifiers(Modifier.PUBLIC) else it }
.addModifiers(Modifier.FINAL)
.let {
if (publicModifier && !description.isNullOrBlank()) {
it.addJavadoc("\$L\n", description)
} else {
it
}
}
.let {
if (publicModifier && isDeprecated ?: false && !deprecationReason.isNullOrBlank()) {
it.addJavadoc("@deprecated \$L\n", deprecationReason)
} else {
it
}
}
.build()
}
fun argumentCodeBlock(): CodeBlock {
if (args == null || args.isEmpty()) {
return CodeBlock.builder().add("null").build()
}
return jsonMapToCodeBlock(args.fold(HashMap(), { map, arg ->
map.put(arg["name"].toString(), arg["value"]!!)
return@fold map
}))
}
fun formatClassName() = responseName.capitalize().let { if (isList()) it.singularize() else it }
fun isOptional(): Boolean = isConditional || !methodResponseType().endsWith("!")
fun isNonScalar() = hasFragments() || (fields?.any() ?: false)
private fun hasFragments() = (fragmentSpreads?.any() ?: false) || (inlineFragments?.any() ?: false)
private fun isList(): Boolean = type.removeSuffix("!").let { it.startsWith('[') && it.endsWith(']') }
private fun jsonMapToCodeBlock(jsonMap: Map): CodeBlock {
return jsonMap.entries.map { entry ->
val codeBuilder = CodeBlock.builder()
if (entry.value is Map<*, *>) {
@Suppress("UNCHECKED_CAST")
codeBuilder.add(".put(\$S, ", entry.key).add("\$L)\n", jsonMapToCodeBlock(entry.value as Map))
} else {
codeBuilder.add(".put(\$S, \$S)\n", entry.key, entry.value).build()
}
codeBuilder.build()
}.fold(CodeBlock.builder().add("new \$T(\$L)\n",
ClassNames.parameterizedUnmodifiableMapBuilderOf(String::class.java, Any::class.java),
jsonMap.size
).indent(), CodeBlock.Builder::add)
.unindent()
.add(".build()").build()
}
private fun toTypeName(responseType: String, context: CodeGenerationContext): TypeName {
val packageName = if (isNonScalar()) "" else context.typesPackage
return JavaTypeResolver(context, packageName, isDeprecated ?: false).resolve(responseType, isOptional())
}
private fun methodResponseType(): String {
if (isNonScalar() || hasFragments()) {
// For non scalar fields, we use the responseName as the method return type.
// However, we need to also encode any extra information from the `type` field
// eg, [lists], nonNulls!, [[nestedLists]], [nonNullLists]!, etc
val normalizedName = formatClassName()
if (type.startsWith("[")) {
// array type
return if (type.endsWith("!")) "[$normalizedName]!" else "[$normalizedName]"
} else if (type.endsWith("!")) {
// non-null type
return "$normalizedName!"
} else {
// nullable type
return normalizedName
}
} else {
return type
}
}
companion object {
val TYPE_NAME_FIELD = Field(responseName = "__typename", fieldName = "__typename", type = "String!")
}
}