com.iflytek.edu.cloud.frame.doc.ServiceDocBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.iflytek.edu.cloud.frame.doc.ServiceDocBuilder.java

Source

/**
 * Copyright 2013-2014 the original author or authors.
 *
 * Licensed 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.iflytek.edu.cloud.frame.doc;

import static java.io.File.separator;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.validation.constraints.NotNull;

import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;

import com.iflytek.edu.cloud.frame.annotation.ServiceMethod;
import com.iflytek.edu.cloud.frame.doc.model.ClassDoc;
import com.iflytek.edu.cloud.frame.doc.model.JavaBeanDoc;
import com.iflytek.edu.cloud.frame.doc.model.JavaBeanDoc.FieldDoc;
import com.iflytek.edu.cloud.frame.doc.model.MethodDoc;
import com.iflytek.edu.cloud.frame.doc.model.ParamDoc;
import com.iflytek.edu.cloud.frame.doc.model.ReturnDoc;
import com.iflytek.edu.cloud.frame.utils.EnvUtil;
import com.iflytek.edu.cloud.frame.utils.SystemPropertyUtil;
import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.Annotation;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.Type;

/**
 * 
 * @author libinsong1204@gmail.com
 *
 */
public class ServiceDocBuilder {
    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceDocBuilder.class);

    private JavaDocBuilder builder;

    public ServiceDocBuilder() {
        builder = new JavaDocBuilder();
        builder.setEncoding("UTF-8");
        addJavaSource();
    }

    public List<ClassDoc> buildDoc() {
        List<ClassDoc> classDocs = new ArrayList<ClassDoc>();

        List<JavaClass> javaClasses = findRestServices();

        for (JavaClass javaClass : javaClasses) {
            ClassDoc classDoc = new ClassDoc();
            classDoc.setServiceDesc(javaClass.getComment());
            classDoc.setServiceName(javaClass.getTagByName("serviceName").getValue());

            List<JavaMethod> javaMethods = findMethods(javaClass);
            for (JavaMethod method : javaMethods) {
                //?
                MethodDoc methodDoc = new MethodDoc();
                Annotation[] annotations = method.getAnnotations();
                for (Annotation ann : annotations) {
                    if (ServiceMethod.class.getName().equals(ann.getType().getFullyQualifiedName())) {
                        String name = (String) ann.getNamedParameter("value");
                        String version = (String) ann.getNamedParameter("version");
                        methodDoc.setName(StringUtils.strip(name.trim(), "\""));
                        methodDoc.setVersion(StringUtils.strip(version.trim(), "\""));
                        break;
                    }
                }
                methodDoc.setDescription(method.getComment());

                //?
                ReturnDoc returnDoc = new ReturnDoc();
                returnDoc.setDataType(method.getReturnType().getFullyQualifiedName());

                if ("java.util.List".equals(returnDoc.getDataType())) {
                    Type type = method.getReturnType().getActualTypeArguments()[0];
                    if (!ClassUtils.isPrimitiveOrWrapper(type.getFullyQualifiedName())) {
                        returnDoc.setBeanName(type.getFullyQualifiedName());
                        JavaBeanDoc beanDoc = getJavaBeanDoc(type.getFullyQualifiedName());
                        classDoc.getBeanDocs().add(beanDoc);
                    }
                }

                if (method.getTagByName("return") == null) {
                    throw new RuntimeException(" " + method.getName() + " return");
                }

                //??? @return userid A2342312 $$ ID 
                String returnDesc = method.getTagByName("return").getValue();
                String[] desces = returnDesc.split("\\$\\$");
                if (desces.length > 1) {
                    returnDoc.setExampleData(desces[0]);
                    returnDoc.setDescription(desces[1]);
                } else {
                    returnDoc.setDescription(returnDesc);
                }

                returnDoc.setDimensions(method.getReturnType().getDimensions());
                methodDoc.setReturnDoc(returnDoc);

                //??
                JavaParameter[] parameters = method.getParameters();
                DocletTag[] paramTags = method.getTagsByName("param");
                for (int i = 0, len = parameters.length; i < len; i++) {
                    JavaParameter parameter = parameters[i];
                    String type = parameter.getType().getFullyQualifiedName();
                    String paramName = parameter.getName();

                    ParamDoc paramDoc = new ParamDoc();
                    paramDoc.setName(paramName);
                    paramDoc.setDataType(type);

                    //????? @param userid A2342312 $$ ID 
                    String paramDesc = getParamDesc(paramName, paramTags);
                    desces = paramDesc.split("\\$\\$");
                    if (desces.length > 1) {
                        paramDoc.setExampleData(desces[0].trim());
                        paramDoc.setDescription(desces[1].trim());
                    } else {
                        paramDoc.setDescription(paramDesc);
                    }

                    methodDoc.getParamDocs().add(paramDoc);

                    //javax.servlet.*
                    if (!ClassUtils.isPrimitiveOrWrapper(type) && !type.startsWith("javax.servlet")) {
                        classDoc.getBeanDocs().add(getJavaBeanDoc(type));
                    }
                }

                classDoc.getMethodDocs().add(methodDoc);
            }

            boolean isNew = true;
            for (ClassDoc doc : classDocs) {
                if (doc.getServiceName().equals(classDoc.getServiceName())) {
                    doc.getBeanDocs().addAll(classDoc.getBeanDocs());
                    doc.getMethodDocs().addAll(classDoc.getMethodDocs());
                    isNew = false;
                    break;
                }
            }

            if (isNew)
                classDocs.add(classDoc);
        }

        return classDocs;
    }

    private JavaBeanDoc getJavaBeanDoc(String type) {
        JavaClass javaClass = builder.getClassByName(type);
        JavaField[] fields = javaClass.getFields();
        JavaBeanDoc beanDoc = new JavaBeanDoc();
        beanDoc.setName(javaClass.getFullyQualifiedName());
        beanDoc.setDescription(javaClass.getComment());
        for (JavaField field : fields) {
            FieldDoc fieldDoc = new FieldDoc();
            fieldDoc.setName(field.getName());
            fieldDoc.setDataType(field.getType().getFullyQualifiedName());
            fieldDoc.setDescription(field.getComment());

            DocletTag tag = field.getTagByName("data");
            if (tag != null)
                fieldDoc.setExampleData(tag.getValue());

            beanDoc.getFieldDocs().add(fieldDoc);

            Annotation[] anns = field.getAnnotations();
            for (Annotation ann : anns) {
                String typeName = ann.getType().getFullyQualifiedName();

                if (NotEmpty.class.getName().equals(typeName) || NotNull.class.getName().equals(typeName)) {
                    fieldDoc.setRequired(true);
                    break;
                }
            }
        }

        return beanDoc;
    }

    /**
     * ???
     * 
     * @return
     */
    private String getParamDesc(String paramName, DocletTag[] paramTags) {
        for (DocletTag tag : paramTags) {
            String desc = tag.getValue();
            if (desc != null && desc.trim().startsWith(paramName)) {
                desc = desc.substring(paramName.length()).trim();
                return desc;
            }
        }

        return "";
    }

    public List<JavaClass> findRestServices() {
        List<JavaClass> restJavaClasses = new ArrayList<JavaClass>();

        JavaClass[] javaClasses = builder.getClasses();
        for (JavaClass javaClass : javaClasses) {
            Annotation[] annotations = javaClass.getAnnotations();
            for (Annotation ann : annotations) {
                if (RestController.class.getName().equals(ann.getType().getFullyQualifiedName())) {
                    restJavaClasses.add(javaClass);
                    break;
                }
            }
        }

        return restJavaClasses;
    }

    public List<JavaMethod> findMethods(JavaClass javaClass) {
        List<JavaMethod> restMethods = new ArrayList<JavaMethod>();

        JavaMethod[] methods = javaClass.getMethods();
        for (JavaMethod method : methods) {
            Annotation[] annotations = method.getAnnotations();
            for (Annotation ann : annotations) {
                if (ServiceMethod.class.getName().equals(ann.getType().getFullyQualifiedName())) {
                    restMethods.add(method);
                    break;
                }
            }
        }

        return restMethods;
    }

    private void addJavaSource() {
        String sourcePath = null;
        if (EnvUtil.isDevelopment()) {
            sourcePath = EnvUtil.getProjectBaseDir() + separator + "src" + separator + "main" + separator + "java";

            File sourceDir = new File(sourcePath);
            builder.addSourceTree(sourceDir);
        } else {
            try {
                sourcePath = SystemPropertyUtil.get("BASE_HOME") + separator + "source" + separator
                        + EnvUtil.getProjectName() + "-" + EnvUtil.getBuildVersion() + "-sources.jar";
                doServiceJavaSource(sourcePath);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

    }

    private void doServiceJavaSource(String jarFileUrl) throws IOException {
        JarFile jarFile = new JarFile(jarFileUrl);
        try {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Looking for matching resources in jar file [" + jarFileUrl + "]");
            }

            for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
                JarEntry entry = entries.nextElement();

                String entryPath = entry.getName();
                if (entryPath.endsWith(".java")) {
                    InputStream inputStream = jarFile.getInputStream(entry);
                    builder.addSource(new InputStreamReader(inputStream, "UTF-8"));
                }
            }
        } finally {
            jarFile.close();
        }
    }
}