Search in sources :

Example 1 with JsonField

use of com.instagram.common.json.annotation.JsonField in project ig-json-parser by Instagram.

the class JsonAnnotationProcessor method processFieldAnnotation.

/**
 * This processes a single field annotated with {@link JsonField}. It locates the enclosing class
 * and then gathers data on the declared type of the field.
 */
private void processFieldAnnotation(Element element) {
    // Verify common generated code restrictions.
    if (!isFieldAnnotationValid(element)) {
        return;
    }
    TypeElement classElement = null;
    if (element.getKind() == PARAMETER) {
        Element constructorElement = (Element) element.getEnclosingElement();
        classElement = (TypeElement) constructorElement.getEnclosingElement();
    } else {
        classElement = (TypeElement) element.getEnclosingElement();
    }
    JsonType jsonTypeAnnotation = classElement.getAnnotation(JsonType.class);
    boolean isStrict = jsonTypeAnnotation.strict();
    boolean isKotlin = isTypeElementKotlin(classElement);
    TypeMirror type = element.asType();
    JsonParserClassData injector = mState.mClassElementToInjectorMap.get(classElement);
    JsonField annotation = element.getAnnotation(JsonField.class);
    TypeData data = injector.getOrCreateRecord(annotation.fieldName().toString());
    boolean isNullable = !isStrict || isFieldElementNullable(element);
    AccessorMetadata accessorMetadata = AccessorMetadata.create(element.getSimpleName().toString(), isStrict, isKotlin, jsonTypeAnnotation.useGetters(), element.getKind());
    if (accessorMetadata.checkMetadataMismatch(data)) {
        error(element, "%s: Detected multiple annotations with the same field name. Field names must be unique within given class.", classElement);
    }
    data.setSerializeType(accessorMetadata.serializeType);
    data.setDeserializeType(accessorMetadata.deserializeType);
    data.setGetterName(accessorMetadata.getterName);
    data.setSetterName(accessorMetadata.setterName);
    data.setMemberVariableName(accessorMetadata.memberVariableName);
    data.setFieldName(annotation.fieldName());
    data.setIsNullable(isNullable);
    data.setAlternateFieldNames(annotation.alternateFieldNames());
    data.setMapping(annotation.mapping());
    data.setValueExtractFormatter(VALUE_EXTRACT.forString(annotation.valueExtractFormatter()));
    data.setAssignmentFormatter(FIELD_ASSIGNMENT.forString(annotation.fieldAssignmentFormatter()));
    data.setSerializeCodeFormatter(FIELD_CODE_SERIALIZATION.forString(annotation.serializeCodeFormatter()));
    TypeUtils.CollectionType collectionType = mTypeUtils.getCollectionType(type);
    data.setCollectionType(collectionType);
    if (collectionType != TypeUtils.CollectionType.NOT_A_COLLECTION) {
        // inspect the inner type.
        type = mTypeUtils.getCollectionParameterizedType(type);
    }
    data.setParseType(mTypeUtils.getParseType(type, JsonType.class));
    boolean skipEnumValidationCheck = setJsonAdapterIfApplicable(type, injector, data, annotation);
    /**
     * UNSUPPORTED can be parsed if valueExtractFormatter and or serializeCodeFormatter have been
     * provided
     */
    if (data.getParseType() == TypeUtils.ParseType.UNSUPPORTED) {
        TypeMirror erasedType = mTypes.erasure(type);
        DeclaredType declaredType = (DeclaredType) erasedType;
        TypeElement typeElement = (TypeElement) declaredType.asElement();
        String packageName = mTypeUtils.getPackageName(mElements, typeElement);
        data.setPackageName(packageName);
        data.setParsableType(mTypeUtils.getClassName(typeElement, packageName));
        CodeFormatter.Factory serializeCodeType = typeElement.getKind() == INTERFACE ? CodeFormatter.CLASS_CODE_SERIALIZATION : CodeFormatter.INTERFACE_CODE_SERIALIZATION;
        data.setIsInterface(typeElement.getKind() == INTERFACE);
        data.setIsWildcard(type != null && type.getKind() == TypeKind.WILDCARD);
    } else if (data.getParseType() == TypeUtils.ParseType.PARSABLE_OBJECT) {
        TypeMirror erasedType = mTypes.erasure(type);
        DeclaredType declaredType = (DeclaredType) erasedType;
        TypeElement typeElement = (TypeElement) declaredType.asElement();
        String packageName = mTypeUtils.getPackageName(mElements, typeElement);
        data.setPackageName(packageName);
        data.setParsableType(mTypeUtils.getClassName(typeElement, packageName));
        data.setParsableTypeParserClass(mTypeUtils.getPrefixForGeneratedClass(typeElement, packageName));
        JsonType typeAnnotation = typeElement.getAnnotation(JsonType.class);
        // Use the parsable object's value extract formatter if existing one is empty
        data.setValueExtractFormatter(data.getValueExtractFormatter().orIfEmpty(VALUE_EXTRACT.forString(typeAnnotation.valueExtractFormatter())));
        CodeFormatter.Factory serializeCodeType = typeElement.getKind() == INTERFACE ? CodeFormatter.CLASS_CODE_SERIALIZATION : CodeFormatter.INTERFACE_CODE_SERIALIZATION;
        data.setSerializeCodeFormatter(data.getSerializeCodeFormatter().orIfEmpty(serializeCodeType.forString(typeAnnotation.serializeCodeFormatter())));
        data.setIsInterface(typeElement.getKind() == INTERFACE);
        data.setIsWildcard(type != null && type.getKind() == TypeKind.WILDCARD);
        data.setFormatterImports(typeAnnotation.typeFormatterImports());
    } else if (data.getParseType() == TypeUtils.ParseType.ENUM_OBJECT) {
        // verify that we have value extract and serializer formatters.
        if (!skipEnumValidationCheck && (StringUtil.isNullOrEmpty(annotation.valueExtractFormatter()) || (injector.generateSerializer() && StringUtil.isNullOrEmpty(annotation.serializeCodeFormatter())))) {
            error(element, "%s: Annotate the enum with @%s (see annotation docs for details). " + "If that is undesirable you must have a value extract formatter, " + "and a serialize code formatter if serialization generation is enabled", classElement, JsonAdapter.class.getSimpleName());
        }
        data.setEnumType(type.toString());
    }
}
Also used : JsonType(com.instagram.common.json.annotation.JsonType) TypeElement(javax.lang.model.element.TypeElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) JsonAdapter(com.instagram.common.json.annotation.JsonAdapter) TypeUtils(com.instagram.common.json.annotation.util.TypeUtils) JsonField(com.instagram.common.json.annotation.JsonField) TypeMirror(javax.lang.model.type.TypeMirror) DeclaredType(javax.lang.model.type.DeclaredType)

Aggregations

JsonAdapter (com.instagram.common.json.annotation.JsonAdapter)1 JsonField (com.instagram.common.json.annotation.JsonField)1 JsonType (com.instagram.common.json.annotation.JsonType)1 TypeUtils (com.instagram.common.json.annotation.util.TypeUtils)1 Element (javax.lang.model.element.Element)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 TypeElement (javax.lang.model.element.TypeElement)1 VariableElement (javax.lang.model.element.VariableElement)1 DeclaredType (javax.lang.model.type.DeclaredType)1 TypeMirror (javax.lang.model.type.TypeMirror)1