All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gsonpath.adapter.standard.model.FieldInfoFactory.kt Maven / Gradle / Ivy

Go to download

An annotation processor which generates Type Adapters for the Google Gson library

The newest version!
package gsonpath.adapter.standard.model

import com.google.gson.annotations.SerializedName
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.TypeName
import gsonpath.ProcessingException
import gsonpath.annotation.ExcludeField
import gsonpath.annotation.NestedJson
import gsonpath.model.FieldInfo
import gsonpath.model.FieldType
import gsonpath.util.*
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
import javax.lang.model.type.TypeMirror

class FieldInfoFactory(
        private val typeHandler: TypeHandler,
        private val fieldTypeFactory: FieldTypeFactory,
        private val fieldGetterFinder: FieldGetterFinder,
        private val annotationFetcher: AnnotationFetcher,
        private val defaultValueDetector: DefaultValueDetector) {

    class InterfaceInfo(
            val parentClassName: ClassName,
            val fieldInfo: List)

    class InterfaceFieldInfo(
            val elementInfo: ElementInfo,
            val typeName: TypeName,
            val typeMirror: TypeMirror,
            val fieldName: String,
            val getterMethodName: String)

    interface ElementInfo {
        val underlyingElement: Element

        fun  getAnnotation(annotationClass: Class): T?

        val annotationNames: List
    }

    /**
     * Obtain all possible elements contained within the annotated class, including inherited fields.
     */
    fun getModelFieldsFromElement(
            modelElement: TypeElement,
            fieldsRequireAnnotation: Boolean,
            useConstructor: Boolean): List {

        val filterFunc: (Element) -> Boolean = {

            // Ignore static and transient fields.
            it.kind == ElementKind.FIELD &&
                    !(it.modifiers.contains(Modifier.STATIC) || it.modifiers.contains(Modifier.TRANSIENT)) &&

                    // If a field is final, we only add it if we are using a constructor to assign it.
                    (!it.modifiers.contains(Modifier.FINAL) || useConstructor) &&

                    (!fieldsRequireAnnotation || it.getAnnotationEx(SerializedName::class.java) != null ||
                            it.getAnnotationEx(NestedJson::class.java) != null) &&

                    // Ignore any excluded fields
                    it.getAnnotationEx(ExcludeField::class.java) == null
        }
        return typeHandler.getFields(modelElement, filterFunc)
                .map { (memberElement, generifiedElement) ->
                    object : FieldInfo {
                        override val fieldType: FieldType
                            get() = fieldTypeFactory.createFieldType(TypeName.get(generifiedElement), generifiedElement)

                        override val parentClassName: String
                            get() = memberElement.enclosingElement.toString()

                        override fun  getAnnotation(annotationClass: Class): T? {
                            return annotationFetcher.getAnnotation(modelElement, memberElement, annotationClass)
                        }

                        override val fieldName: String
                            get() = memberElement.simpleName.toString()

                        override val fieldAccessor: String
                            get() {
                                return if (!memberElement.modifiers.contains(Modifier.PRIVATE)) {
                                    memberElement.simpleName.toString()
                                } else {
                                    findFieldGetterMethodName(modelElement, memberElement) + "()"
                                }
                            }

                        override val annotationNames: List
                            get() {
                                return annotationFetcher.getAnnotationMirrors(modelElement, memberElement)
                                        .map { it.annotationType.asElement().simpleName.toString() }
                            }

                        override val element: Element
                            get() = memberElement

                        override val hasDefaultValue: Boolean
                            get() = defaultValueDetector.hasDefaultValue(memberElement)
                    }
                }
    }

    /**
     * Attempts to find a logical getter method name for a variable.
     *
     * @param modelElement the parent element of the field.
     * @param variableElement the field element we want to find the getter method for.
     */
    private fun findFieldGetterMethodName(modelElement: TypeElement, variableElement: Element): String {
        val method = fieldGetterFinder.findGetter(modelElement, variableElement)
                ?: throw ProcessingException("Unable to find getter for private variable", variableElement)

        return method.simpleName.toString()
    }

    fun getModelFieldsFromInterface(interfaceInfo: InterfaceInfo): List {
        return interfaceInfo.fieldInfo.map {
            object : FieldInfo {
                override val fieldType: FieldType
                    get() = fieldTypeFactory.createFieldType(it.typeName, it.typeMirror)

                override val parentClassName: String
                    get() = interfaceInfo.parentClassName.toString()

                override fun  getAnnotation(annotationClass: Class): T? {
                    return it.elementInfo.getAnnotation(annotationClass)
                }

                override val fieldName: String
                    get() = it.fieldName

                override val fieldAccessor: String
                    get() = it.getterMethodName + "()"

                override val annotationNames: List
                    get() = it.elementInfo.annotationNames

                override val element: Element
                    get() = it.elementInfo.underlyingElement

                override val hasDefaultValue: Boolean
                    get() = false
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy