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

com.dchan.jaxb.VisitorPlugin Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
package com.dchan.jaxb;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JPackage;
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;

import com.sun.tools.xjc.outline.Aspect;
import com.sun.tools.xjc.model.CClassInfoParent;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
import com.sun.tools.xjc.outline.PackageOutline;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;

public class VisitorPlugin extends Plugin {
    
    private String packageName;
    private boolean includeType = false;

    private boolean generateClasses = true;

    @Override
    public String getOptionName() {
        return "Xvisitor";
    }

    @Override
    public String getUsage() {
        return null;
    }
    
    @Override
    public int parseArgument(Options opt, String[] args, int index) throws BadCommandLineException, IOException {
    	
    	// look for the visitor-package argument since we'll use this for package name for our generated code.
        String arg = args[index];
        if (arg.startsWith("-Xvisitor-package:")) {
            packageName = arg.split(":")[1];
            return 1;
        }
        if (arg.startsWith("-Xvisitor-includeType:")) {
            includeType = "true".equalsIgnoreCase(arg.split(":")[1]);
            return 1;
        }
        if (arg.equals("-Xvisitor-includeType")) {
            includeType = true;
            return 1;
        }
        if (arg.equals("-Xvisitor-noClasses")) {
            generateClasses = false;
            return 1;
        }
        return 0;
    }

    @Override
    public boolean run(Outline outline, Options options, ErrorHandler errorHandler)
            throws SAXException {
        try {

            JPackage vizPackage = getOrCreatePackageForVisitors(outline);

            Set sorted = sortClasses(outline);

            Set directClasses = ClassDiscoverer.discoverDirectClasses(outline, sorted);

            CreateJAXBElementNameCallback cni =
                    new CreateJAXBElementNameCallback(outline, vizPackage);
            cni.run(sorted, directClasses);

            Function visitMethodNamer;
            Function traverseMethodNamer;
            if (includeType) {
                visitMethodNamer = s -> "visit" + s;
                traverseMethodNamer = s -> "traverse" + s;
            } else {
                visitMethodNamer = s -> "visit";
                traverseMethodNamer = s -> "traverse";
            }


            // create visitor interface
            CreateVisitorInterface createVisitorInterface =
                    new CreateVisitorInterface(outline, vizPackage, visitMethodNamer);
            createVisitorInterface.run(sorted, directClasses);
            JDefinedClass visitor = createVisitorInterface.getOutput();
            
            // create visitable interface and have all the beans implement it
            CreateVisitableInterface createVisitableInterface =
                    new CreateVisitableInterface(visitor, outline, vizPackage);
            createVisitableInterface.run(sorted, directClasses);
            JDefinedClass visitable = createVisitableInterface.getOutput();
            
            // add accept method to beans
            AddAcceptMethod addAcceptMethod = new AddAcceptMethod(visitMethodNamer);
            addAcceptMethod.run(sorted, visitor);
            
            // create traverser interface
            CreateTraverserInterface createTraverserInterface =
                    new CreateTraverserInterface(visitor, outline, vizPackage, traverseMethodNamer);
            createTraverserInterface.run(sorted, directClasses);
            JDefinedClass traverser = createTraverserInterface.getOutput();

            // create progress monitor for traversing visitor
            CreateTraversingVisitorProgressMonitorInterface progMon =
                    new CreateTraversingVisitorProgressMonitorInterface(
                            outline, vizPackage);
            progMon.run(sorted, directClasses);
            JDefinedClass progressMonitor = progMon.getOutput();

            if (generateClasses) {
                // create base visitor class
                CreateBaseVisitorClass createBaseVisitorClass =
                        new CreateBaseVisitorClass(visitor, outline, vizPackage, visitMethodNamer);
                createBaseVisitorClass.run(sorted, directClasses);

                // create default generic depth first traverser class
                CreateDepthFirstTraverserClass createDepthFirstTraverserClass =
                        new CreateDepthFirstTraverserClass(visitor, traverser,
                                visitable, outline, vizPackage, traverseMethodNamer);
                createDepthFirstTraverserClass.run(sorted, directClasses);

                // create traversing visitor class
                CreateTraversingVisitorClass createTraversingVisitorClass =
                        new CreateTraversingVisitorClass(visitor, progressMonitor,
                                traverser, outline, vizPackage, visitMethodNamer, traverseMethodNamer);
                createTraversingVisitorClass.run(sorted, directClasses);
            }
        } catch (Throwable t) {
            t.printStackTrace();
            return false;
        }
        return true;
    }

    private Set sortClasses(Outline outline) {
        Set sorted = new TreeSet<>((aOne, aTwo) -> {
            String one = aOne.implClass.fullName();
            String two = aTwo.implClass.fullName();
            return one.compareTo(two);
        });
        sorted.addAll(outline.getClasses());
        return sorted;
    }

    private JPackage getOrCreatePackageForVisitors(Outline outline) {
        JPackage vizPackage = null;
        if (getPackageName() != null) {
            JPackage root = outline.getCodeModel().rootPackage();
            String[] packages = getPackageName().split("\\.");
            JPackage current = root;
            for(String p : packages) {
                current = current.subPackage(p);
            }
            vizPackage = current;
        }
        if (vizPackage == null) {
            PackageOutline packageOutline = outline.getAllPackageContexts().iterator().next();
            CClassInfoParent.Package pkage = new CClassInfoParent.Package(packageOutline._package());
            vizPackage = (JPackage) outline.getContainer(pkage, Aspect.IMPLEMENTATION);
        }
        return vizPackage;
    }
    
    @SuppressWarnings("WeakerAccess")
    public String getPackageName() {
        return packageName;
    }

    @SuppressWarnings("UnusedDeclaration")
    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy