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

com.ly.doc.template.IDocBuildTemplate Maven / Gradle / Ivy

Go to download

Smart-doc is a tool that supports both JAVA RESTFUL API and Apache Dubbo RPC interface document generation.

There is a newer version: 3.0.5
Show newest version
/*
 * Copyright (C) 2018-2023 smart-doc
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.ly.doc.template;

import com.ly.doc.builder.ProjectDocConfigBuilder;
import com.ly.doc.constants.TornaConstants;
import com.ly.doc.helper.DocBuildHelper;
import com.ly.doc.model.dependency.FileDiff;
import com.ly.doc.model.*;
import com.ly.doc.model.annotation.FrameworkAnnotations;
import com.ly.doc.utils.DocPathUtil;
import com.ly.doc.utils.DocUtil;
import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author yu 2019/12/21.
 */
public interface IDocBuildTemplate {

    default List getApiData(ProjectDocConfigBuilder projectBuilder) {
        DocBuildHelper docBuildHelper = DocBuildHelper.create(projectBuilder);

        preRender(docBuildHelper);

        Collection candidateClasses = getCandidateClasses(projectBuilder, docBuildHelper);
        List apiList = renderApi(projectBuilder, candidateClasses);

        postRender(docBuildHelper, apiList);

        return apiList;
    }

    List renderApi(ProjectDocConfigBuilder projectBuilder, Collection candidateClasses);

    FrameworkAnnotations registeredAnnotations();

    /**
     * handle group api docs
     *
     * @param apiDocList list of apiDocList
     * @param apiConfig  ApiConfig apiConfig
     * @return List of ApiDoc
     * @author cqmike
     */
    default List handleApiGroup(List apiDocList, ApiConfig apiConfig) {
        if (CollectionUtil.isEmpty(apiDocList) || apiConfig == null) {
            return apiDocList;
        }
        List groups = apiConfig.getGroups();
        List finalApiDocs = new ArrayList<>();

        ApiDoc defaultGroup = ApiDoc.buildGroupApiDoc(TornaConstants.DEFAULT_GROUP_CODE);
        // show default group
        AtomicInteger order = new AtomicInteger(1);
        finalApiDocs.add(defaultGroup);

        if (CollectionUtil.isEmpty(groups)) {
            defaultGroup.setOrder(order.getAndIncrement());
            defaultGroup.getChildrenApiDocs().addAll(apiDocList);
            return finalApiDocs;
        }
        Map hasInsert = new HashMap<>();
        for (ApiGroup group : groups) {
            ApiDoc groupApiDoc = ApiDoc.buildGroupApiDoc(group.getName());
            finalApiDocs.add(groupApiDoc);
            for (ApiDoc doc : apiDocList) {
                if (hasInsert.containsKey(doc.getAlias())) {
                    continue;
                }
                if (!DocUtil.isMatch(group.getApis(), doc.getPackageName() + "." + doc.getName())) {
                    continue;
                }
                hasInsert.put(doc.getAlias(), null);
                groupApiDoc.getChildrenApiDocs().add(doc);
                doc.setOrder(groupApiDoc.getChildrenApiDocs().size());
                doc.setGroup(group.getName());
                if (StringUtil.isEmpty(group.getPaths())) {
                    continue;
                }
                List methodDocs = doc.getList().stream()
                        .filter(l -> DocPathUtil.matches(l.getPath(), group.getPaths(), null))
                        .collect(Collectors.toList());
                doc.setList(methodDocs);
            }
        }
        // Ungrouped join the default group
        for (ApiDoc doc : apiDocList) {
            String key = doc.getAlias();
            if (!hasInsert.containsKey(key)) {
                defaultGroup.getChildrenApiDocs().add(doc);
                doc.setOrder(defaultGroup.getChildrenApiDocs().size());
                hasInsert.put(doc.getAlias(), null);
            }
        }
        if (CollectionUtil.isEmpty(defaultGroup.getChildrenApiDocs())) {
            finalApiDocs.remove(defaultGroup);
        }
        finalApiDocs.forEach(group -> group.setOrder(order.getAndIncrement()));
        return finalApiDocs;
    }

    /**
     * If build doc incrementally, we will filter the classes changed
     * from the commit-id in increment-config-file.
     * If not, we will return all classes.
     *
     * @param docBuilder      docBuilder
     * @param docBuildHelper incrementHelper
     * @return the candidate classes
     */
    default Collection getCandidateClasses(ProjectDocConfigBuilder docBuilder, DocBuildHelper docBuildHelper) {
        ApiConfig apiConfig = docBuilder.getApiConfig();
        JavaProjectBuilder javaProjectBuilder = docBuilder.getJavaProjectBuilder();

        if (!apiConfig.isIncrement()) {
            return javaProjectBuilder.getClasses();
        }

        if (docBuildHelper.notGitRepo() || StringUtil.isEmpty(docBuildHelper.getDependencyTree().getCommitId())) {
            // There is no commit-id, which means the user haven't built the whole project.
            // We need to build the whole project this time,
            // and record the latest commit-id and the newest api dependency tree.
            return javaProjectBuilder.getClasses();
        }

        Set fileDiffList = docBuildHelper.getChangedFilesFromVCS(new Predicate() {
            @Override
            public boolean test(String s) {
                return isEntryPoint(javaProjectBuilder, s);
            }
        });
        if (CollectionUtil.isEmpty(fileDiffList)) {
            return Collections.emptyList();
        }

        Collection result = new ArrayList<>(fileDiffList.size());
        fileDiffList.forEach(item -> {
            try {
                JavaClass javaClass = javaProjectBuilder.getClassByName(item.getNewQualifiedName());
                result.add(javaClass);
            } catch (Exception ignore) {}
        });

        return result;
    }

    default void preRender(DocBuildHelper docBuildHelper) {

    }

    default void postRender(DocBuildHelper docBuildHelper, List apiList) {
        docBuildHelper.rebuildDependencyTree(apiList);
    }

    default boolean isEntryPoint(JavaProjectBuilder javaProjectBuilder, String javaClassName) {
        if (StringUtil.isEmpty(javaClassName)) {
            return false;
        }

        JavaClass javaClass = null;
        try {
            javaClass = javaProjectBuilder.getClassByName(javaClassName);
        } catch (Exception ignore) {}

        if (javaClass == null) {
            return false;
        }

        return isEntryPoint(javaClass, registeredAnnotations());
    }

    boolean isEntryPoint(JavaClass javaClass, FrameworkAnnotations frameworkAnnotations);

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy