org.panopticode.doclet.PanopticodeDoclet.java Source code

Java tutorial

Introduction

Here is the source code for org.panopticode.doclet.PanopticodeDoclet.java

Source

/*
 * Copyright (c) 2006-2007 Julias R. Shaw
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
package org.panopticode.doclet;

import com.sun.javadoc.*;
import org.panopticode.*;
import org.dom4j.io.*;

import java.io.*;
import java.util.List;
import java.util.LinkedList;

public class PanopticodeDoclet extends Doclet {
    private static PanopticodeDoclet doclet = new PanopticodeDoclet();

    private PanopticodeProject project;
    private RootDoc rootDoc;

    public static LanguageVersion languageVersion() {
        return LanguageVersion.JAVA_1_5;
    }

    public static int optionLength(final String option) {
        if (option.equals("-debug") || option.equals("-outputFile") || option.equals("-projectName")
                || option.equals("-projectVersion")) {
            return 2;
        }

        return 0;
    }

    public static boolean start(final RootDoc rootDoc) {
        try {
            doclet.process(rootDoc);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static PanopticodeProject getProject() {
        return doclet.project;
    }

    void dumpXMLReport(PanopticodeProject theProject) throws IOException {
        PrintStream output;
        String outputFile;
        XMLWriter xmlWriter;

        outputFile = readOption("outputFile");

        if (outputFile == null) {
            output = System.out;
        } else {
            output = new PrintStream(outputFile);
        }

        xmlWriter = new XMLWriter(output, OutputFormat.createPrettyPrint());
        xmlWriter.write(theProject.generateXMLDocument());
    }

    void gatherStructure(RootDoc theRootDoc, PanopticodeProject theProject) throws IOException {
        for (ClassDoc classDoc : theRootDoc.classes()) {
            loadClassInfo(classDoc, theProject);
        }
    }

    private void loadClassInfo(ClassDoc classDoc, PanopticodeProject theProject) throws IOException {
        String packageName = classDoc.containingPackage().name();

        PanopticodePackage panopticodePackage = theProject.createAndAddPackage(packageName);

        SourcePosition classPosition = classDoc.position();

        String filePath = classPosition.file().getCanonicalPath();
        String fileName = classPosition.file().getName();

        PanopticodeFile panopticodeFile = panopticodePackage.createAndAddFile(filePath, fileName);
        PanopticodeClass panopticodeClass = panopticodeFile.createAndAddClass(classDoc.name(), classPosition.line(),
                classPosition.column());

        panopticodeClass.setEnum(classDoc.isEnum());
        panopticodeClass.setInterface(classDoc.isInterface());
        panopticodeClass.setStatic(classDoc.isStatic());
        panopticodeClass.setAbstract(classDoc.isAbstract());

        addMethods(panopticodeClass, classDoc.constructors(true), true);
        addMethods(panopticodeClass, classDoc.methods(true), false);

        for (ClassDoc innerClassDoc : classDoc.innerClasses(false)) {
            loadClassInfo(innerClassDoc, theProject);
        }
    }

    /*
     * The isSynthetic call seems to be broken for default contructors.  This seems to fix it.
     */
    private boolean syntheticConstructor(ExecutableMemberDoc executableMemberDoc, PanopticodeClass panopticodeClass,
            boolean isConstructor) {
        SourcePosition methodPosition = executableMemberDoc.position();
        int line = methodPosition.line();
        int column = methodPosition.column();

        return (isConstructor && line == panopticodeClass.getPositionLine()
                && column == panopticodeClass.getPositionColumn());
    }

    private void addMethods(PanopticodeClass panopticodeClass, ExecutableMemberDoc[] executableMemberDocs,
            boolean areConstructors) {
        for (ExecutableMemberDoc executableMemberDoc : executableMemberDocs) {
            if (!syntheticConstructor(executableMemberDoc, panopticodeClass, areConstructors)) {
                int column;
                int line;
                List<PanopticodeArgument> arguments;
                PanopticodeMethod panopticodeMethod;
                String methodName;

                methodName = executableMemberDoc.name();
                arguments = new LinkedList<PanopticodeArgument>();
                PanopticodeArgument lastArgument = null;
                for (Parameter parameter : executableMemberDoc.parameters()) {
                    PanopticodeArgument panopticodeArgument;
                    String parameterName;
                    String parameterQualifiedType;
                    String parameterType;

                    parameterName = parameter.name();
                    parameterQualifiedType = parameter.type().qualifiedTypeName() + parameter.type().dimension();
                    parameterType = parameter.type().simpleTypeName() + parameter.type().dimension();
                    panopticodeArgument = new PanopticodeArgument(parameterName, parameterQualifiedType,
                            parameterType);
                    arguments.add(panopticodeArgument);

                    if (parameter.type().asParameterizedType() != null) {
                        panopticodeArgument.setParameterizedType(true);
                    }

                    lastArgument = panopticodeArgument;
                }

                if (lastArgument != null && executableMemberDoc.isVarArgs()) {
                    lastArgument.setVarArg(true);
                }

                SourcePosition methodPosition = executableMemberDoc.position();
                line = methodPosition.line();
                column = methodPosition.column();

                panopticodeMethod = panopticodeClass.createAndAddMethod(methodName, arguments, line, column);
                panopticodeMethod.setParentClass(panopticodeClass);
                if (!areConstructors && ((MethodDoc) executableMemberDoc).isAbstract()) {
                    panopticodeMethod.setAbstract(true);
                }
                panopticodeMethod.setConstructor(areConstructors);
            }
        }
    }

    private void process(RootDoc theRootDoc) throws IOException {
        boolean debug;
        long dumpXMLTime;
        long gatherStructureTime;
        long startTime;

        startTime = System.currentTimeMillis();

        rootDoc = theRootDoc;
        debug = "true".equalsIgnoreCase(readOption("debug"));
        project = new PanopticodeProject(readOption("projectName"), System.getProperty("user.dir"));
        project.setVersion(readOption("projectVersion"));

        gatherStructure(rootDoc, project);
        gatherStructureTime = System.currentTimeMillis();

        dumpXMLReport(project);
        dumpXMLTime = System.currentTimeMillis();

        if (debug) {
            System.out.println("Doclet Time: " + (dumpXMLTime - startTime) + "ms");
            System.out.println("\tTime to gather structure: " + (gatherStructureTime - startTime) + "ms");
            System.out.println("\tTime to dump XML: " + (dumpXMLTime - gatherStructureTime) + "ms");
        }
    }

    private String readOption(String tagName) {
        String[] optionArray = readOptionArray(tagName);

        if (optionArray != null) {
            return optionArray[1];
        }

        return null;
    }

    private String[] readOptionArray(String tagName) {
        String[][] options = rootDoc.options();

        for (String[] opt : options) {
            if (opt[0].equals("-" + tagName)) {
                return opt;
            }
        }

        return null;
    }
}