Package restx.apidocs.doclet

Source Code of restx.apidocs.doclet.ApidocsDoclet$NoTrace

package restx.apidocs.doclet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.io.Files;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationDesc.ElementValuePair;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.DocErrorReporter;
import com.sun.javadoc.Doclet;
import com.sun.javadoc.LanguageVersion;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.ParamTag;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.standard.Standard;
import org.joda.time.DateTime;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.util.Arrays.asList;

/**
* ApidocsDoclet.
*
* Extracts javadoc of RESTX endpoints to provide them in API DOCS.
*/
public class ApidocsDoclet extends Doclet {

    /**
     * The starting point of Javadoc render.
     *
     * _Javadoc spec requirement._
     *
     * @param rootDoc input class documents
     * @return success
     */
    @SuppressWarnings("UnusedDeclaration")
    public static boolean start(RootDoc rootDoc) {
        Path targetDir = Paths.get(Options.TARGET_DIR.getOption(rootDoc.options()).or(""));

        rootDoc.printNotice("generating RESTX apidocs notes in: " + targetDir + " ...");

        Path apidocsTarget = targetDir.resolve("apidocs");
        if (!apidocsTarget.toFile().exists()) {
            apidocsTarget.toFile().mkdirs();
        }

        Trace trace = Options.ENABLE_TRACE.isSet(rootDoc.options()) ?
                new FileTrace(targetDir.resolve("apidoclet.trace").toFile()) :
                new NoTrace()
                ;

        trace.trace("RESTX APIDOCLET " + DateTime.now());
        trace.trace("target dir : " + targetDir.toAbsolutePath());
        trace.trace("current dir: " + Paths.get("").toAbsolutePath());

        ObjectMapper mapper = new ObjectMapper();

        for (ClassDoc classDoc : rootDoc.classes()) {

            ApiEntryNotes entryNotes = new ApiEntryNotes().setName(classDoc.qualifiedName());

            for (MethodDoc methodDoc : classDoc.methods()) {
                for (AnnotationDesc annotationDesc : methodDoc.annotations()) {
                    if (annotationDesc.annotationType().qualifiedName().startsWith("restx.annotations.")) {
                        Optional<Object> value = getAnnotationParamValue(annotationDesc.elementValues(), "value");

                        if (value.isPresent()) {
                            trace.trace(classDoc.name() + " > " + methodDoc.qualifiedName() + " > " + annotationDesc.annotationType().name());
                            trace.trace(asList(annotationDesc.elementValues()).toString());
                            trace.trace(methodDoc.commentText());

                            ApiOperationNotes operation = new ApiOperationNotes()
                                    .setHttpMethod(annotationDesc.annotationType().name())
                                    .setPath(String.valueOf(value.get()))
                                    .setNotes(methodDoc.commentText());

                            for (ParamTag paramTag : methodDoc.paramTags()) {
                                trace.trace("\t" + paramTag.parameterName() + " > " + paramTag.parameterComment());

                                operation.getParameters().add(
                                        new ApiParameterNotes()
                                                .setName(paramTag.parameterName())
                                                .setNotes(paramTag.parameterComment()));
                            }

                            for (Tag aReturn : methodDoc.tags("return")) {
                                trace.trace("\t" + aReturn.name() + " > " + aReturn.text());

                                operation.getParameters().add(
                                        new ApiParameterNotes()
                                                .setName("response")
                                                .setNotes(aReturn.text()));
                            }

                            entryNotes.getOperations().add(operation);
                        }
                    }
                }
            }

            if (!entryNotes.getOperations().isEmpty()) {
                Path doc = apidocsTarget.resolve(classDoc.qualifiedName() + ".notes.json");
                rootDoc.printNotice("generating RESTX API entry notes for " + classDoc.qualifiedName() + " ...");
                trace.trace("generating notes in " + doc.toAbsolutePath());
                try {
                    mapper.writeValue(doc.toFile(), entryNotes);
                } catch (IOException e) {
                    trace.trace("can't write to api doc file " + doc.toFile() + ": " + e);
                    rootDoc.printError("can't write to api doc file " + doc.toFile() + ": " + e);
                }
            } else {
                trace.trace("no operations found on " + entryNotes.getName());
            }
        }

        if (Options.DISABLE_STANDARD_DOCLET.isSet(rootDoc.options())) {
            return true;
        }

        return Standard.start(rootDoc);
    }

    private static Optional<Object> getAnnotationParamValue(ElementValuePair[] elementValuePairs, String paramName) {
        for (ElementValuePair pair : elementValuePairs) {
            if (pair.element().name().equals(paramName)) {
                return Optional.of(pair.value().value());
            }
        }

        return Optional.absent();
    }


    /**
     * Sets the language version to Java 5.
     *
     * _Javadoc spec requirement._
     *
     * @return language version number
     */
    @SuppressWarnings("UnusedDeclaration")
    public static LanguageVersion languageVersion() {
        return LanguageVersion.JAVA_1_5;
    }

    /**
     * Sets the option length to the standard Javadoc option length.
     *
     * _Javadoc spec requirement._
     *
     * @param option input option
     * @return length of required parameters
     */
    @SuppressWarnings("UnusedDeclaration")
    public static int optionLength(String option) {
        for (Options opt : Options.values()) {
            if (opt.getOptionName().equalsIgnoreCase(option)) {
                return opt.getOptionLength();
            }
        }

        return Standard.optionLength(option);
    }

    /**
     * Processes the input options by delegating to the standard handler.
     *
     * _Javadoc spec requirement._
     *
     * @param options input option array
     * @param errorReporter error handling
     * @return success
     */
    @SuppressWarnings("UnusedDeclaration")
    public static boolean validOptions(String[][] options, DocErrorReporter errorReporter) {
        return Standard.validOptions(options, errorReporter);
    }

    static enum Options {
        DISABLE_STANDARD_DOCLET("-disable-standard-doclet", 1),
        TARGET_DIR("-restx-target-dir", 2),
        ENABLE_TRACE("-restx-enable-trace", 1);

        private final String optionName;
        private final int optionLength;

        Options(String name, int optionLength) {
            this.optionName = name;
            this.optionLength = optionLength;
        }

        public String getOptionName() {
            return optionName;
        }

        public int getOptionLength() {
            return optionLength;
        }

        public boolean isSet(String[][] options) {
            for (String[] option : options) {
                if (options.length > 0 && optionName.equals(option[0])) {
                    return true;
                }
            }

            return false;
        }

        public Optional<String> getOption(String[][] options) {
            for (String[] option : options) {
                if (options.length > 1 && optionName.equals(option[0])) {
                    return Optional.of(option[1]);
                }
            }
            return Optional.absent();
        }
    }

    private static interface Trace {
        public void trace(String msg);
    }

    private static class FileTrace implements Trace {
        private final File traceFile;

        private FileTrace(File traceFile) {
            this.traceFile = traceFile;
        }

        @Override
        public void trace(String msg) {
            try {
                Files.append(msg + "\n", traceFile, Charsets.UTF_8);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static class NoTrace implements Trace {
        @Override
        public void trace(String msg) {
        }
    }
}
TOP

Related Classes of restx.apidocs.doclet.ApidocsDoclet$NoTrace

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.
div>