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

com.github.aidensuen.mongo.builder.annotation.MongoDaoAnnotationBuilder Maven / Gradle / Ivy

There is a newer version: 1.1.2
Show newest version
package com.github.aidensuen.mongo.builder.annotation;

import com.github.aidensuen.mongo.annotation.*;
import com.github.aidensuen.mongo.builder.MongoDaoBuilder;
import com.github.aidensuen.mongo.command.CommandSource;
import com.github.aidensuen.mongo.command.DynamicCommandSource;
import com.github.aidensuen.mongo.command.OperationType;
import com.github.aidensuen.mongo.core.MongoDaoStatement;
import com.github.aidensuen.mongo.exception.BindingException;
import com.github.aidensuen.mongo.exception.IncompleteElementException;
import com.github.aidensuen.mongo.mapping.AggregateInfo;
import com.github.aidensuen.mongo.mapping.DynamicCommand;
import com.github.aidensuen.mongo.mapping.UpdateInfo;
import com.github.aidensuen.mongo.parsing.DynamicCommandParser;
import com.github.aidensuen.mongo.reflection.ParamNameResolver;
import com.github.aidensuen.mongo.session.Configuration;
import com.github.aidensuen.util.ReflectionUtil;
import com.github.aidensuen.util.StringUtil;
import org.springframework.data.mongodb.repository.Query;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class MongoDaoAnnotationBuilder implements MongoDaoBuilder {

    private static final Set> Command_ANNOTATION_TYPES = new HashSet<>();
    private static final Set> Command_PROVIDER_ANNOTATION_TYPES = new HashSet<>();

    static {
        Command_ANNOTATION_TYPES.add(Find.class);
        Command_ANNOTATION_TYPES.add(Insert.class);
        Command_ANNOTATION_TYPES.add(Update.class);
        Command_ANNOTATION_TYPES.add(Delete.class);

        Command_PROVIDER_ANNOTATION_TYPES.add(FindProvider.class);
        Command_PROVIDER_ANNOTATION_TYPES.add(InsertProvider.class);
        Command_PROVIDER_ANNOTATION_TYPES.add(UpdateProvider.class);
        Command_PROVIDER_ANNOTATION_TYPES.add(DeleteProvider.class);
    }

    private final Configuration configuration;
    private final Class implementType;

    public MongoDaoAnnotationBuilder(Configuration configuration, Class implementType) {
        this.configuration = configuration;
        this.implementType = implementType;
    }

    @Override
    public void parse() {
        Method[] methods = implementType.getMethods();
        for (Method method : methods) {
            try {
                if (!method.isBridge()) {
                    parseStatement(method);
                }
            } catch (IncompleteElementException e) {
                configuration.addIncompleteMethod(new MethodResolver(this, method));
            }
        }
    }

    void parseStatement(Method method) {
        MongoDaoStatement.Builder builder = new MongoDaoStatement.Builder(this.configuration);
        builder.implementationClass(implementType);

        ParamNameResolver resolver = new ParamNameResolver(configuration, method, implementType);
        String id = StringUtil.appendStrs(implementType.getName(), ".", method.getName(), "-@params", StringUtil.concat(resolver.getMethodClassNames()));

        resolveCommonInfo(id, method, builder);
        resolveCommandSource(resolver, method, builder);

        MongoDaoStatement statement = builder.build();
        this.configuration.addMongoDaoStatement(statement);
    }

    private void resolveCommonInfo(String statement, Method method, MongoDaoStatement.Builder builder) {
        Class commandAnnotationType = getCommandAnnotationType(method);
        Class commandProviderAnnotationType = getCommandProviderAnnotationType(method);
        Annotation annotation = null;
        if (commandAnnotationType != null) {
            if (commandProviderAnnotationType != null) {
                throw new BindingException("You cannot supply both a static Command and CommandProvider to method named " + method.getName());
            }
            annotation = method.getAnnotation(commandAnnotationType);
        } else if (commandProviderAnnotationType != null) {
            annotation = method.getAnnotation(commandProviderAnnotationType);
        }
        OperationType operationType = getOperationType(annotation);
        Class entityClass = getEntityClass(annotation);
        Set updateFields = new HashSet<>();
        updateFields.addAll(Arrays.asList(getUpdateFields(annotation)));
        boolean nullable = getNullable(annotation);
        UpdateInfo info = new UpdateInfo(StringUtil.toStringArray(updateFields), nullable);
        Class inputType = getInputType(annotation);
        Class outputType = getOutputType(annotation);
        String options = getOptions(annotation);
        if (Object.class.equals(entityClass)) {
            // get entityClass from generic interfaces
            entityClass = this.configuration.getEntityClass(statement);
        }
        if (Object.class.equals(inputType)) {
            // get entityClass from generic interfaces
            inputType = this.configuration.getEntityClass(statement);
        }
        if (Object.class.equals(outputType)) {
            // get entityClass from generic interfaces
            outputType = this.configuration.getEntityClass(statement);
        }
        builder.id(statement).methodName(method.getName()).operationType(operationType).methodName(method.getName()).entityClass(entityClass).updateInfo(info).aggregeteInfo(new AggregateInfo(inputType, outputType, options));
    }

    private OperationType getOperationType(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "operationType", annotation, OperationType.class);
        } catch (Exception e) {

        }
        return null;
    }

    private Class getEntityClass(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "entityClass", annotation, Class.class);
        } catch (Exception e) {

        }
        return null;
    }

    private String[] getUpdateFields(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "value", annotation, String[].class);
        } catch (Exception e) {

        }
        return new String[]{};
    }

    private boolean getNullable(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "nullable", annotation, Boolean.class);
        } catch (Exception e) {

        }
        return false;
    }

    private Class getInputType(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "inputType", annotation, Class.class);
        } catch (Exception e) {

        }
        return null;
    }

    private Class getOutputType(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "outputType", annotation, Class.class);
        } catch (Exception e) {

        }
        return null;
    }

    private String getOptions(Annotation annotation) {
        try {
            return ReflectionUtil.invokeMethod(annotation.getClass(), "options", annotation, String.class);
        } catch (Exception e) {

        }
        return null;
    }


    private void resolveCommandSource(ParamNameResolver resolver, Method method, MongoDaoStatement.Builder builder) {
        String[] names = resolver.getNames();
        CommandSource commandSource = null;
        String fields = null;
        String sortFields = null;
        boolean hasCommandAnnotation = false;
        if (method.isAnnotationPresent(Query.class)) {
            Query queryAnno = method.getAnnotation(Query.class);
            String dynamicCommand = queryAnno.value();
            DynamicCommand command = new DynamicCommand(dynamicCommand);
            commandSource = new DynamicCommandSource(this.configuration, command);
            fields = queryAnno.fields();
            sortFields = queryAnno.sort();
            hasCommandAnnotation = true;
        } else if (method.isAnnotationPresent(Pipeline.class)) {
            Pipeline pipelineAnno = method.getAnnotation(Pipeline.class);
            String dynamicCommand = pipelineAnno.value();
            if (StringUtil.isEmpty(dynamicCommand)) {
                dynamicCommand = pipelineAnno.pipeline();
            }
            DynamicCommand command = new DynamicCommand(dynamicCommand);
            commandSource = new DynamicCommandSource(this.configuration, command);
            hasCommandAnnotation = true;
        } else {
            if (supportCommandSource(builder)) {
                DynamicCommandParser parser = new DynamicCommandParser(resolver, builder);
                commandSource = new DynamicCommandSource(this.configuration, parser.parser());
            }
        }
        builder.paramNames(names).returnFields(fields).sortFields(sortFields).hasCommandAnnotation(hasCommandAnnotation).mongoCommand(commandSource);
    }

    private boolean supportCommandSource(MongoDaoStatement.Builder builder) {
        OperationType type = builder.build().getOperationType();
        return type != OperationType.SAVE && type != OperationType.INSERT && type != OperationType.UNKNOWN;
    }

    private Class getCommandAnnotationType(Method method) {
        return chooseAnnotationType(method, Command_ANNOTATION_TYPES);
    }

    private Class getCommandProviderAnnotationType(Method method) {
        return chooseAnnotationType(method, Command_PROVIDER_ANNOTATION_TYPES);
    }

    private Class chooseAnnotationType(Method method, Set> types) {
        for (Class type : types) {
            Annotation annotation = method.getAnnotation(type);
            if (annotation != null) {
                return type;
            }
        }
        return null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy