001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2024 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.site; 021 022import java.nio.file.Path; 023import java.nio.file.Paths; 024import java.util.Locale; 025 026import org.apache.maven.doxia.macro.AbstractMacro; 027import org.apache.maven.doxia.macro.Macro; 028import org.apache.maven.doxia.macro.MacroExecutionException; 029import org.apache.maven.doxia.macro.MacroRequest; 030import org.apache.maven.doxia.module.xdoc.XdocSink; 031import org.apache.maven.doxia.sink.Sink; 032import org.codehaus.plexus.component.annotations.Component; 033 034/** 035 * A macro that inserts a link to the parent module. 036 */ 037@Component(role = Macro.class, hint = "parent-module") 038public class ParentModuleMacro extends AbstractMacro { 039 @Override 040 public void execute(Sink sink, MacroRequest request) throws MacroExecutionException { 041 // until https://github.com/checkstyle/checkstyle/issues/13426 042 if (!(sink instanceof XdocSink)) { 043 throw new MacroExecutionException("Expected Sink to be an XdocSink."); 044 } 045 final String moduleName = (String) request.getParameter("moduleName"); 046 final Object instance = SiteUtil.getModuleInstance(moduleName); 047 final Class<?> clss = instance.getClass(); 048 createParentModuleParagraph((XdocSink) sink, clss, moduleName); 049 } 050 051 /** 052 * Creates a paragraph with a link to the parent module. 053 * 054 * @param sink the sink to write to. 055 * @param clss the class of the module. 056 * @param moduleName the module name. 057 * @throws MacroExecutionException if the parent module cannot be found. 058 */ 059 private static void createParentModuleParagraph(XdocSink sink, Class<?> clss, String moduleName) 060 throws MacroExecutionException { 061 final String parentModule = SiteUtil.getParentModule(clss); 062 final String linkToParentModule = getLinkToParentModule(parentModule, moduleName); 063 064 sink.setInsertNewline(false); 065 sink.paragraph(); 066 sink.setInsertNewline(true); 067 final String indentLevel10 = SiteUtil.getNewlineAndIndentSpaces(10); 068 sink.rawText(indentLevel10); 069 sink.link(linkToParentModule); 070 sink.text(parentModule); 071 sink.link_(); 072 final String indentLevel8 = SiteUtil.getNewlineAndIndentSpaces(8); 073 sink.rawText(indentLevel8); 074 sink.paragraph_(); 075 } 076 077 /** 078 * Returns relative link to the parent module for the given module class. 079 * 080 * @param parentModule parent module name. 081 * @param moduleName the module name we are looking for the parent of. 082 * @return relative link to the parent module. 083 * @throws MacroExecutionException if link to the parent module cannot be constructed. 084 */ 085 private static String getLinkToParentModule(String parentModule, String moduleName) 086 throws MacroExecutionException { 087 final Path templatePath = SiteUtil.getTemplatePath(moduleName); 088 if (templatePath == null) { 089 throw new MacroExecutionException( 090 String.format(Locale.ROOT, "Could not find template for %s", moduleName)); 091 } 092 final Path templatePathParent = templatePath.getParent(); 093 if (templatePathParent == null) { 094 throw new MacroExecutionException("Failed to get parent path for " + templatePath); 095 } 096 return templatePathParent 097 .relativize(Paths.get("src", "xdocs", "config.xml")) 098 .toString() 099 .replace(".xml", ".html") 100 .replace('\\', '/') 101 + "#" + parentModule; 102 } 103}