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

io.virtdata.apps.docsapp.AutoDocsApp Maven / Gradle / Ivy

package io.virtdata.apps.docsapp;

import com.vladsch.flexmark.convert.html.FlexmarkHtmlParser;
import io.virtdata.annotations.Category;
import io.virtdata.core.VirtDataDocs;
import io.virtdata.processors.DocCtorData;
import io.virtdata.processors.DocFuncData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.security.InvalidParameterException;
import java.util.*;
import java.util.stream.Collectors;

public class AutoDocsApp {
    private final static Logger logger = LoggerFactory.getLogger(AutoDocsApp.class);
    private final static String SPLIT = "split";
    private final static String COMBINED = "combined";
    private final static String ALL = "all";
    private final static String DEFAULT_FILE="funcref";
    private final static String fileExtension=".md";

    // category -> funcname -> [docfuncdata, ...]
    private Map>> groupedModels = new HashMap<>();

    private String baseFileName = DEFAULT_FILE;
    private String print = ALL;
    private String categories = SPLIT;

    public static void main(String[] args) {
        new AutoDocsApp().invoke(args);
    }

    private void invoke(String[] args) {
        LinkedList largs = new LinkedList<>(Arrays.asList(args));
        while (largs.peekFirst() != null) {
            String argtype = largs.removeFirst();
            if (largs.peekFirst() == null) {
                throw new RuntimeException(AutoDocsApp.class.toString() + " expects args in param value couplets.");
            }
            String argval = largs.removeFirst().toLowerCase();
            switch (argtype) {
                case "output":
                    this.baseFileName = argval;
                    break;
                case "print":
                    if (argval.equals("all") || argval.equals("logs")) {
                        this.print = argval;
                    } else {
                        throw new InvalidParameterException("valid args for print: print all, print logs");
                    }
                case "categories":
                    if (!argval.equals(SPLIT) && !argval.equals(COMBINED)) {
                        throw new RuntimeException("categories must either be " + SPLIT + ", or " + COMBINED + ".");
                    }
                    categories = argval;
                    break;
                default:
            }
        }

        List docModels = VirtDataDocs.getAllDocs();
        for (DocFuncData docModel : docModels) {
            for (Category category : docModel.getCategories()) {
                Map> category_funcname_list = this.groupedModels.get(category);
                if (category_funcname_list == null) {
                    category_funcname_list = new HashMap<>();
                    this.groupedModels.put(category, category_funcname_list);
                }
                List group = category_funcname_list.getOrDefault(docModel.getClassName(), new ArrayList<>());
                group.add(docModel);
                category_funcname_list.put(docModel.getClassName(), group);
            }
        }


        StringBuilder sb = new StringBuilder();
//        Map docsByCategory=new HashMap<>();

        Map> assignments = new HashMap<>();
        // Map single category annotation to global Name -> Category assignment
        for (DocFuncData docModel : docModels) {

            Set listForFuncName = assignments.getOrDefault(docModel.getClassName(), new HashSet<>());
            assignments.put(docModel.getClassName(),listForFuncName);
            if (listForFuncName.size()>0) {
                logger.warn("Func name " +  docModel.getClassName() + " has " + listForFuncName.size() + " multiple category annotations:");
            }
            listForFuncName.addAll(Arrays.asList(docModel.getCategories()));
            logger.info("Assigning " + docModel.getClassName() + " to categories " + listForFuncName.toString());
        }

        Set generalSet = new HashSet() {{ add(Category.general); }};
        // regroup docs under categories
        // category -> funcname -> [docfuncdata, ...]
        Map>> regrouped = new HashMap<>();
        for (DocFuncData docModel : docModels) {
            Set assignment = assignments.getOrDefault(docModel.getClassName(), generalSet);
            if (assignment.size()==0) {
                assignment=generalSet;
            }
            logger.info("looking up assignment for " + docModel.getClassName() +":" + assignment.toString());
            for (Category category : assignment) {
                Map> assignToCategory = regrouped.getOrDefault(category, new HashMap<>());
                regrouped.put(category,assignToCategory);

                List assignToClass = assignToCategory.getOrDefault(docModel.getClassName(), new ArrayList<>());
                assignToCategory.put(docModel.getClassName(),assignToClass);

                assignToClass.add(docModel);
            }
        }
        groupedModels=regrouped;


        Map writers = new HashMap<>();
        Writer writer = new OutputStreamWriter(System.out);
        try {

            for (Category category : Category.values()) {
                if (groupedModels.keySet().contains(category)) {

                    if (!this.baseFileName.isEmpty() && this.categories.equals(SPLIT)) {
                        writer = writers.getOrDefault(category.toString(), new FileWriter(baseFileName + "_" + category.toString() + fileExtension));
                    } else if (!this.baseFileName.isEmpty() && this.categories.equals(COMBINED)) {
                        writer = writers.getOrDefault(baseFileName + fileExtension, new FileWriter(baseFileName));
                    }

                    String docs = writeCategoryDocs(category, groupedModels.get(category));
                    //docs = replacePatterns(docs);
                    writer.write(docs);
                    writer.flush();
                }
            }
            for (Writer writer1 : writers.values()) {
                writer1.close();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String replacePatterns(String docdata) {
        docdata = docdata.replaceAll("","Object>");
        docdata = docdata.replaceAll("java.lang.", "");
        docdata = docdata.replaceAll("^\\s*\\s*\n", "\n```\n");
        docdata = docdata.replaceAll("(

|

| \n)+", "\n"); docdata = docdata.replaceAll("
", "`");
        docdata = docdata.replaceAll("
", "`"); docdata = docdata.replaceAll("\\{@link (.+?)}", "$1"); docdata = docdata.replaceAll("(?m)@param .*\n", ""); docdata = docdata.replaceAll("(?m)\n\n+", "\n\n"); docdata = docdata.replaceAll("(?m)\\[]...:","..."); docdata = docdata.replaceAll("(?m)@see ","See "); return docdata; } private String writeCategoryDocs(Category category, Map> groupedDocs) { StringBuilder sb = new StringBuilder(); ArrayList funcNames = new ArrayList<>(groupedDocs.keySet()); Collections.sort(funcNames); sb.append("# CATEGORY ").append(category).append("\n"); for (String name : funcNames) { List docs = groupedDocs.get(name); sb.append("## ").append(name).append("\n\n"); List classdocs = docs.stream() .filter(d -> d.getClassJavadoc() != null && !d.getClassJavadoc().isEmpty()) .collect(Collectors.toList()); List distinctClassDocs = classdocs.stream() .map(DocFuncData::getClassJavadoc) .map(String::trim) .distinct() .collect(Collectors.toList()); if (distinctClassDocs.size() == 0) { logger.warn("There were no class docs found for types named " + name); } if (distinctClassDocs.size() > 1) { logger.warn("There were multiple class docs found for types named " + name); } if (distinctClassDocs.size() == 1) { String classdoc = distinctClassDocs.get(0); classdoc = parseHtmlToMarkdown(classdoc); sb.append(classdoc); if (!classdoc.endsWith("\n\n")) { sb.append("\n"); } if (!classdoc.endsWith("\n")) { sb.append("\n"); } } for (DocFuncData doc : docs) { List ctors = doc.getCtors(); for (DocCtorData ctor : ctors) { sb.append("- ").append(doc.getInType()).append(" -> "); sb.append(doc.getClassName()); sb.append("("); sb.append( ctor.getArgs().entrySet().stream().map( e -> e.getValue() + ": " + e.getKey() ).collect(Collectors.joining(", ")) ); sb.append(")"); sb.append(" -> ").append(doc.getOutType()).append("\n"); String ctorDoc = ctor.getCtorJavaDoc(); if (!ctorDoc.isEmpty()) { sb.append(" - *notes:* ").append(ctorDoc); } for (List example : ctor.getExamples()) { sb.append(" - *ex:* `").append(example.get(0)).append("`"); if (example.size() > 1) { sb.append(" - *").append(example.get(1)).append("*"); } sb.append("\n"); } } } sb.append("\n"); sb.append("\n"); } return sb.toString(); } private String parseHtmlToMarkdown(String classdoc) { String markdown = FlexmarkHtmlParser.parse(classdoc); return markdown; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy