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

pocketknife.internal.codegen.injection.IntentInjectionProcessor Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
package pocketknife.internal.codegen.injection;

import pocketknife.InjectExtra;
import pocketknife.NotRequired;
import pocketknife.internal.codegen.IntentFieldBinding;
import pocketknife.internal.codegen.InvalidTypeException;
import pocketknife.internal.codegen.KeySpec;

import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static pocketknife.internal.GeneratedAdapters.INTENT_ADAPTER_SUFFIX;

public class IntentInjectionProcessor extends InjectionProcessor {

    public IntentInjectionProcessor(Messager messager, Elements elements, Types types) {
        super(messager, elements, types);
    }

    public Map findAndParseTargets(RoundEnvironment env) {
        Map targetClassMap = new LinkedHashMap();
        Set erasedTargetNames = new LinkedHashSet();

        // Process each @InjectExtra
        for (Element element : env.getElementsAnnotatedWith(InjectExtra.class)) {
            try {
                parseInjectExtra(element, targetClassMap, erasedTargetNames);
            } catch (Exception e) {
                StringWriter stackTrace = new StringWriter();
                e.printStackTrace(new PrintWriter(stackTrace));
                error(element, "Unable to generate intent adapter for @InjectExtra.\n\n%s", stackTrace);
            }
        }

        // Try to find a parent adapter for each adapter
        for (Map.Entry entry : targetClassMap.entrySet()) {
            TypeElement parent = findParent(entry.getKey(), erasedTargetNames);
            if (parent != null) {
                entry.getValue().setParentAdapter(getPackageName(parent), parent.getSimpleName() + INTENT_ADAPTER_SUFFIX);
            }
        }

        return targetClassMap;
    }

    private void parseInjectExtra(Element element, Map targetClassMap, Set erasedTargetNames)
            throws InvalidTypeException {
        TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

        // Verify that the target has all the appropriate information for type
        TypeMirror type = element.asType();
        if (type instanceof TypeVariable) {
            TypeVariable typeVariable = (TypeVariable) type;
            type = typeVariable.getUpperBound();
        }

        validateNotRequiredArguments(element);
        validateForCodeGeneration(InjectExtra.class, element);
        validateBindingPackage(InjectExtra.class, element);

        // Assemble information on the injection point
        String name = element.getSimpleName().toString();
        String intentType = typeUtil.getIntentType(type);
        KeySpec key = getKey(element);
        boolean required = element.getAnnotation(NotRequired.class) == null;
        boolean hasDefault = typeUtil.isPrimitive(type);
        boolean needsToBeCast = typeUtil.needToCastIntentType(type);

        IntentInjectionAdapterGenerator intentInjectionAdapterGenerator = getOrCreateTargetClass(targetClassMap, enclosingElement);
        IntentFieldBinding binding = new IntentFieldBinding(name, type, intentType, key, needsToBeCast, hasDefault, required);
        intentInjectionAdapterGenerator.addField(binding);

        // Add the type-erased version to the valid targets set.
        erasedTargetNames.add(enclosingElement.toString());
    }

    private KeySpec getKey(Element element) {
        if (isDefaultAnnotationElement(element, InjectExtra.class.getName(), "value")) {
            return new KeySpec(null, generateKey(IntentFieldBinding.KEY_PREFIX, element.getSimpleName().toString()));
        }
        return new KeySpec(null, element.getAnnotation(InjectExtra.class).value());
    }

    private IntentInjectionAdapterGenerator getOrCreateTargetClass(Map targetClassMap,
                                                                   TypeElement enclosingElement) {
        IntentInjectionAdapterGenerator intentInjectionAdapterGenerator = targetClassMap.get(enclosingElement);
        if (intentInjectionAdapterGenerator == null) {
            TypeMirror targetType = enclosingElement.asType();
            String classPackage = getPackageName(enclosingElement);
            String className = getClassName(enclosingElement, classPackage) + INTENT_ADAPTER_SUFFIX;

            intentInjectionAdapterGenerator = new IntentInjectionAdapterGenerator(classPackage, className, targetType, typeUtil);
            targetClassMap.put(enclosingElement, intentInjectionAdapterGenerator);
        }
        return intentInjectionAdapterGenerator;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy