Package scenic3.apt.processor

Source Code of scenic3.apt.processor.Scenic3Processor$Visitor

package scenic3.apt.processor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.ExecutableDeclaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.ParameterDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.util.DeclarationFilter;
import com.sun.mirror.util.SimpleDeclarationVisitor;

import java.util.List;
import scenic3.ActionPath;
import scenic3.apt.AnnotationConstants;
import scenic3.apt.Argument;
import scenic3.apt.ScenicControllerDesc;
import scenic3.apt.ScenicControllerGenerator;
import scenic3.apt.UnsupportedArgumentException;
import scenic3.apt.UrlMatcherDesc;
import scenic3.apt.UrlMatcherGenerator;
import scenic3.util.PathUtil;

/**
* {@link AnnotationProcessor} for Scenic3
* @author shuji.w6e
* @since 0.1.0
*/
public class Scenic3Processor implements AnnotationProcessor {

    private final AnnotationProcessorEnvironment env;
    private final Set<AnnotationTypeDeclaration> annotationTypeDeclarations;
    /** Slim3 root package. */
    protected final String rootPackage;
    protected final EnvSupport support;
    private final AnnotationTypeDeclaration pageDecl;

    Scenic3Processor(Set<AnnotationTypeDeclaration> annotationTypeDeclarations, AnnotationProcessorEnvironment env) {
        this.annotationTypeDeclarations = annotationTypeDeclarations;
        this.env = env;
        this.support = new EnvSupport(env);
        String slim3Root = this.env.getOptions().get("slim3.rootPackage");
        // BUG? apt-maven-plugin
        // http://jira.codehaus.org/browse/MOJO-1319
        if (slim3Root == null) {
            for (Entry<String, String> entry : this.env.getOptions().entrySet()) {
                String key = entry.getKey(); // key:
                // -Aslim3.rootPackage=xxx.xxxx,
                // value: null
                if (key.startsWith("-Aslim3.rootPackage")) {
                    slim3Root = key.substring(key.indexOf('=') + 1);
                    break;
                }
            }
        }
        // --- END BUG?
        rootPackage = slim3Root;
        if (rootPackage == null) {
            support.messager.printError("slim3rootPackage is not set. -Aslim3.rootPackage=xxx.xxx");
        }
        // declaration of annotation
        pageDecl = (AnnotationTypeDeclaration) env.getTypeDeclaration(AnnotationConstants.PAGE);
    }

    // process each @Page
    @Override
    public void process() {
        for (ClassDeclaration classDecl : DeclarationFilter.getFilter(ClassDeclaration.class).filter(
                env.getDeclarationsAnnotatedWith(pageDecl), ClassDeclaration.class)) {
            Visitor visitor = new Visitor();
            classDecl.accept(visitor);
            for (MethodDeclaration methodDecl : classDecl.getMethods()) {
                methodDecl.accept(visitor);
            }
            if (visitor.patterns.isEmpty() && visitor.defaultPattern == null) continue;
            String packageName = rootPackage + ".controller.matcher";
            String className = classDecl.getSimpleName() + "Matcher";
            UrlMatcherDesc desc = new UrlMatcherDesc(packageName, className, visitor.pageClassName, visitor.pagePath, visitor.patterns, visitor.defaultPattern);
            try {
                PrintWriter writer = env.getFiler().createSourceFile(packageName + "." + className);
                new UrlMatcherGenerator(desc, writer).generate();
            } catch (Throwable e) {
                support.messager.printError(e.getMessage());
            }
        }
    }

    class Visitor extends SimpleDeclarationVisitor {
        String pageClassName;
        String pagePath;
        SortedMap<ActionPath, String> patterns = new TreeMap<ActionPath, String>();
        String defaultPattern = null;

        // visit class declaration
        // and read @Page'value to set pagePath
        @Override
        public void visitTypeDeclaration(TypeDeclaration d) {
            this.pageClassName = d.getQualifiedName();
            for (AnnotationMirror mirror : d.getAnnotationMirrors()) {
                if (support.isTypeOf(mirror, AnnotationConstants.PAGE)) {
                    this.pagePath = support.getValue(mirror, "value");
                    if (!PathUtil.startsWithSlash(pagePath)) {
                        support.messager.printError("@Page do *not* have value start with a slash.");
                        throw new IllegalStateException("@Page do *not* have value start with a slash.");
                    }
                    return;
                }
            }
        }

        @Override
        public void visitExecutableDeclaration(ExecutableDeclaration d) {
            if (d.getAnnotationMirrors().isEmpty()) return;
            try {
                boolean hasDefault = false;
                String actionPath = null;
                String method = null;
                for (AnnotationMirror mirror : d.getAnnotationMirrors()) {
                    if (support.isTypeOf(mirror, AnnotationConstants.DEFAULT)) {
                        hasDefault = true;
                    } else if (support.isTypeOf(mirror, AnnotationConstants.ACTION_PATH)) {
                        actionPath = support.getValue(mirror, "value");
                        if (PathUtil.startsWithSlash(actionPath)) {
                            support.messager.printError("@ActionPath start with slash.");
                            throw new IllegalStateException("@ActionPath start with slash.");
                        }
                    } else if (support.isTypeOf(mirror, AnnotationConstants.GET)) {
                        if (method != null) {
                            support.messager.printError("@GET can't set with @" + method);
                            throw new IllegalStateException("@GET can't set with @" + method);
                        }
                        method = "GET";
                    } else if (support.isTypeOf(mirror, AnnotationConstants.POST)) {
                        if (method != null) {
                            support.messager.printError("@POST can't set with @" + method);
                            throw new IllegalStateException("@POST can't set with @" + method);
                        }
                        method = "POST";
                    } else if (support.isTypeOf(mirror, AnnotationConstants.PUT)) {
                        if (method != null) {
                            support.messager.printError("@PUT can't set with @" + method);
                            throw new IllegalStateException("@PUT can't set with @" + method);
                        }
                        method = "PUT";
                    } else if (support.isTypeOf(mirror, AnnotationConstants.DELETE)) {
                        if (method != null) {
                            support.messager.printError("@DELETE can't set with @" + method);
                            throw new IllegalStateException("@DELETE can't set with @" + method);
                        }
                        method = "DELETE";
                    }
                }
                if (hasDefault && actionPath != null) {
                    support.messager.printWarning("Has both @Default and @ActionPath. :");
                    return;
                } else if (!hasDefault && actionPath == null) {
                    // not target method
                    return;
                }
                if (hasDefault) {
                    defaultPattern = generate(d, null, method).qName;
                } else if (actionPath != null) {
                    patterns.put(new ActionPath(actionPath, method), generate(d, actionPath, method).qName);
                }
            } catch (IOException e) {
                support.printError(e.getMessage());
            } catch (UnsupportedArgumentException e) {
                support.printError(e.getMessage());
            }
        }

        protected ScenicControllerDesc generate(ExecutableDeclaration d, String actionPath, String method)
                throws UnsupportedArgumentException, IOException {
            ArrayList<Argument> args = new ArrayList<Argument>();
            OUTER_LOOP: for (ParameterDeclaration param : d.getParameters()) {
                String name = param.getSimpleName(); // name
                String type = param.getType().toString(); // type
                // annotation param
                for (AnnotationMirror mirror : param.getAnnotationMirrors()) {
                    if (support.isTypeOf(mirror, AnnotationConstants.REQUEST_PARAM)) {
                        String p = support.getValue(mirror, "value");
                        if (support.containsValue(mirror, "defaultValue")) {
//                            Object obj = support.getValue(mirror, "defaultValue");
//                            throw new IllegalStateException("obj: " + obj.getClass());
                            Collection<AnnotationValue> dvs = support.getValue(mirror, "defaultValue");
                            List<String> dvList = new ArrayList<String>();
                            for (AnnotationValue v : dvs) {
                              dvList.add((String)v.getValue());
                            }
                            String[] dvArray = dvs.isEmpty() ? null : dvList.toArray(new String[0]);
                            args.add(Argument.paramsInstance(type, name, p, dvArray));
                        } else {
                            args.add(Argument.paramInstance(type, name, p, null));
                        }
                        continue OUTER_LOOP;
                    } else if (support.isTypeOf(mirror, AnnotationConstants.VAR)) {
                        String v = support.getValue(mirror, "value");
                        args.add(Argument.varInstance(type, name, v));
                        continue OUTER_LOOP;
                    }
                }
                // simple param
                args.add(Argument.simpleInstance(type, name));
            }
            ScenicControllerDesc desc = new ScenicControllerDesc(pageClassName, rootPackage, pagePath, actionPath,
                    d.getSimpleName(), method, args.toArray(new Argument[args.size()]));
            PrintWriter writer = env.getFiler().createSourceFile(desc.qName);
            ScenicControllerGenerator generator = new ScenicControllerGenerator(desc, writer);
            generator.generate();
            return desc;
        }
    }

}
TOP

Related Classes of scenic3.apt.processor.Scenic3Processor$Visitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.