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

com.duoec.doc.parser.project.MavenProjectParse Maven / Gradle / Ivy

package com.duoec.doc.parser.project;

import com.duoec.doc.DuoDocletConfig;
import com.duoec.doc.constants.DuoDocletConstants;
import com.duoec.doc.doclet.pojo.Artifact;
import com.duoec.doc.doclet.pojo.Project;
import com.duoec.doc.exceptions.DuoDocException;
import com.duoec.doc.utils.CollectionUtils;
import com.duoec.doc.utils.Logger;
import com.duoec.doc.utils.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xuwenzhen
 */
public class MavenProjectParse implements ProjectParse {
    private static final Logger logger = Logger.getLogger(MavenProjectParse.class);
    private static final String STR_GROUP_ID = "groupId";
    private static final String STR_ARTIFACT_ID = "artifactId";
    private static final String STR_VERSION = "version";
    private static final String STR_NAME = "name";
    private static final String STR_DESCRIPTION = "description";
    private static final String STR_PARENT = "parent";
    private static final String STR_PROPERTIES = "properties";
    private static final String STR_PROFILES = "profiles";
    private static final String STR_ACTIVATION = "activation";
    private static final String STR_ACTIVE_BY_DEFAULT = "activeByDefault";
    private static final String STR_TRUE = "true";

    private static final Map PROJECT_MAP = new HashMap<>();

    /**
     * 获取配置文件
     *
     * @param dir 检查的目录
     */
    @Override
    public File getConfigFile(String dir) {
        if (dir.endsWith(DuoDocletConstants.OBLIQUE_LINE_STR)) {
            dir = dir.substring(0, dir.length() - 1);
        }
        return new File(dir + "/pom.xml");
    }

    /**
     * 匹配配置信息
     *
     * @param pomFile 配置文件
     */
    @Override
    public Project parse(File pomFile) {
        Project project = PROJECT_MAP.get(pomFile);
        if (project != null) {
            return project;
        }
        logger.info("准备解析 pom.xml: " + pomFile.getAbsolutePath());
        //解析 pom.xml
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder;
        Document doc;
        try {
            dBuilder = dbFactory.newDocumentBuilder();
            doc = dBuilder.parse(pomFile);
        } catch (Exception e) {
            throw new DuoDocException("解析 pom.xml 失败!", e);
        }

        Element projectNode = doc.getDocumentElement();
        projectNode.normalize();

        project = new Project();
        Artifact artifact = getArtifact(projectNode);
        project.setArtifact(artifact);

        project.setAppId(DuoDocletConfig.appId);

        String name = getSingleChildElementText(projectNode, STR_NAME);
        project.setName(name);

        String description = getSingleChildElementText(projectNode, STR_DESCRIPTION);
        project.setDescription(description);
        PROJECT_MAP.put(pomFile, project);
        return project;
    }

    private Artifact getArtifact(Element projectNode) {
        NodeList parentNodes = projectNode.getElementsByTagName(STR_PARENT);
        Element parentElement = parentNodes.getLength() > 0 ? (Element) parentNodes.item(0) : null;
        String groupId = getSingleChildElementText(projectNode, STR_GROUP_ID);
        if (StringUtils.isEmpty(groupId) && parentElement != null) {
            groupId = getSingleChildElementText(parentElement, STR_GROUP_ID);
        }

        String artifactId = getSingleChildElementText(projectNode, STR_ARTIFACT_ID);
        if (StringUtils.isEmpty(artifactId) && parentElement != null) {
            artifactId = getSingleChildElementText(parentElement, STR_ARTIFACT_ID);
        }

        String version = getSingleChildElementText(projectNode, STR_VERSION);
        if (StringUtils.isEmpty(version) && parentElement != null) {
            version = getSingleChildElementText(parentElement, STR_VERSION);
        }

        if (version != null && version.startsWith("${") && version.endsWith("}")) {
            //如果version是 ${} 形式的,需要替换变量
            version = version.substring(2, version.length() - 1);
            Map properties = getProjectProperties(projectNode);
            version = properties.get(version);
        }

        Artifact artifact = new Artifact();
        artifact.setGroupId(groupId);
        artifact.setArtifactId(artifactId);
        artifact.setVersion(version);
        return artifact;
    }

    private Map getProjectProperties(Element projectNode) {
        Element propertiesElement = getSingleChildElementChildrenByTagName(projectNode, STR_PROPERTIES);
        Map properties = getPropertiesFrom(propertiesElement);

        Element profilesElement = getSingleChildElementChildrenByTagName(projectNode, STR_PROFILES);
        if (profilesElement != null) {
            NodeList ps = profilesElement.getChildNodes();
            for (int i = 0; i < ps.getLength(); i++) {
                Node p = ps.item(i);
                if (p instanceof Element) {
                    Element profileElement = (Element) p;
                    if (isActiveProfile(profileElement)) {
                        Map profileProperties = getPropertiesFrom(getSingleChildElementChildrenByTagName(profileElement, STR_PROPERTIES));
                        properties.putAll(profileProperties);
                    }
                }
            }
        }

        return properties;
    }

    private boolean isActiveProfile(Element profileElement) {
        Element activationElement = getSingleChildElementChildrenByTagName(profileElement, STR_ACTIVATION);
        if (activationElement == null) {
            return false;
        }
        String activeByDefault = getSingleChildElementText(activationElement, STR_ACTIVE_BY_DEFAULT);
        return STR_TRUE.equalsIgnoreCase(activeByDefault);
    }

    private Map getPropertiesFrom(Element propertiesElement) {
        Map properties = new HashMap<>(8);

        if (propertiesElement == null) {
            return properties;
        }
        NodeList ps = propertiesElement.getChildNodes();
        for (int i = 0; i < ps.getLength(); i++) {
            Node p = ps.item(i);
            if (p instanceof Element) {
                Element propertyElement = (Element) p;
                String name = propertyElement.getTagName();
                String value = propertyElement.getTextContent();
                properties.put(name, value);
            }
        }
        return properties;
    }

    private String getSingleChildElementText(Element parentElement, String tagName) {
        Element childElement = getSingleChildElementChildrenByTagName(parentElement, tagName);
        return childElement != null ? childElement.getTextContent() : null;
    }

    private Element getSingleChildElementChildrenByTagName(Element parentElement, String tagName) {
        List elements = getElementChildrenByTagName(parentElement, tagName);
        if (CollectionUtils.isEmpty(elements)) {
            return null;
        }

        if (elements.size() > 1) {
            throw new DuoDocException("标签 " + tagName + " 存在多个!");
        }
        return elements.get(0);
    }

    private List getElementChildrenByTagName(Element parentElement, String tagName) {
        List elements = new ArrayList<>();
        NodeList childNodes = parentElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            if (childNodes.item(i) instanceof Element) {
                Element childElement = (Element) childNodes.item(i);
                if (tagName.equals(childElement.getTagName())) {
                    //如果标签名相同,返回
                    elements.add(childElement);
                }
            }
        }
        return elements;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy