package com.freetmp.mbg.comment; import com.freetmp.mbg.dom.ExtendedDocument; import com.freetmp.mbg.i18n.Resources; import org.apache.commons.lang3.StringUtils; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.OutputUtilities; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.*; import org.mybatis.generator.config.PropertyRegistry; import org.mybatis.generator.internal.DefaultCommentGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.text.SimpleDateFormat; import java.util.*; import static org.mybatis.generator.internal.util.StringUtility.isTrue; /* * Created by LiuPin on 2015/2/14. */ public class CommentGenerator extends DefaultCommentGenerator { private static final Logger LOG = LoggerFactory.getLogger(CommentGenerator.class); public static final String XMBG_CG_I18N_PATH_KEY = "i18n_path_key_for_CG"; public static final String XMBG_CG_PROJECT_START_YEAR = "project_start_year_for_copyright"; public static final String XMBG_CG_I18N_LOCALE_KEY = "i18n_locale_key_for_CG"; public static final String XMBG_CG_I18N_DEFAULT_PATH = "i18n_for_CG"; public static final String XMBG_CG_PROJECT_START_DEFAULT_YEAR; static { XMBG_CG_PROJECT_START_DEFAULT_YEAR = "" + Calendar.getInstance().get(Calendar.YEAR); } protected ThreadLocal<XmlElement> rootElement = new ThreadLocal<>(); protected boolean suppressAllComments; protected boolean suppressDate; protected SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); protected Resources comments; protected Resources defaultComments; protected Resources copyrights; protected Resources defaultCopyrights; protected String startYear; protected String endYear; protected String i18nPath = XMBG_CG_I18N_DEFAULT_PATH; public CommentGenerator() { super(); } private void initResources(Locale locale) throws MalformedURLException { defaultComments = new Resources(XMBG_CG_I18N_DEFAULT_PATH + "/Comments",locale); defaultCopyrights = new Resources(XMBG_CG_I18N_DEFAULT_PATH + "/Copyrights",locale); ClassLoader loader = getClass().getClassLoader(); // add user specified i18n sources directory to the classpath if(!i18nPath.equals(XMBG_CG_I18N_DEFAULT_PATH)) { URL[] urls = {new File(i18nPath).toURI().toURL()}; loader = new URLClassLoader(urls); comments = new Resources("Comments",locale,loader); copyrights = new Resources("Copyrights",locale,loader); }else { comments = defaultComments; copyrights = defaultCopyrights; } endYear = "" + Calendar.getInstance().get(Calendar.YEAR); } /* * This method returns a formated date string to include in the Javadoc tag * and XML comments. You may return null if you do not want the date in * these documentation elements. * * @return a string representing the current timestamp, or null */ @Override protected String getDateString() { return sdf.format(new Date()); } @Override public void addConfigurationProperties(Properties properties) { super.addConfigurationProperties(properties); // stolen from the parent suppressDate = isTrue(properties .getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE)); suppressAllComments = isTrue(properties .getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS)); if(suppressAllComments) return; // 获取国际化资源的路径 i18nPath = properties.getProperty(XMBG_CG_I18N_PATH_KEY, XMBG_CG_I18N_DEFAULT_PATH); LOG.info("use the i18n resources under {}",i18nPath); // 获取项目开始时间,用在版权声明中 String startYearStr = properties.getProperty(XMBG_CG_PROJECT_START_YEAR); if(StringUtils.isNotEmpty(startYearStr)){ startYear = startYearStr; }else{ startYear = XMBG_CG_PROJECT_START_DEFAULT_YEAR; } // 初始化资源 String localeStr = properties.getProperty(XMBG_CG_I18N_LOCALE_KEY); Locale locale = Locale.getDefault(); if(localeStr != null && StringUtils.isNoneEmpty(localeStr)) { String[] localeAras = localeStr.trim().split("_"); locale = new Locale(localeAras[0], localeAras[1]); } LOG.info("use the locale {}",locale); try { initResources(locale); } catch (MalformedURLException e) { e.printStackTrace(); } } @Override public void addJavaFileComment(CompilationUnit compilationUnit) { // if user doesn't supplied the java source copyright then use the default String copyright = copyrights.getFormatted("JavaSource", startYear, endYear); if(StringUtils.isEmpty(copyright)){ copyright = defaultCopyrights.getFormatted("JavaSource",startYear,endYear); if(StringUtils.isEmpty(copyright)) return; } String[] array = copyright.split("\\|"); for(String str : array){ if(str.startsWith("*")){ str = " " + str; } compilationUnit.addFileCommentLine(str); } } /* * 添加新元素到子元素的最前面 */ public void addToFirstChildren(XmlElement parent,Element child){ List<Element> elements = parent.getElements(); elements.add(0,child); } /* * add the sql map file comment * @param document mbg dom */ public void addSqlMapFileComment(Document document){ if(suppressAllComments) return; ExtendedDocument ed = null; if(document instanceof ExtendedDocument) { ed = (ExtendedDocument) document; } else return; // if user doesn't supplied the xml source copyright then use the default String copyright = copyrights.getFormatted("XmlSource", startYear, endYear); if(StringUtils.isEmpty(copyright)){ copyright = defaultCopyrights.getFormatted("XmlSource",startYear,endYear); } if(StringUtils.isNotEmpty(copyright)) { String[] array = copyright.split("\\|"); StringBuilder sb = new StringBuilder(); for(String str : array){ if(!str.startsWith("<!--") && !str.startsWith("-->")){ sb.append(" "); } sb.append(str); OutputUtilities.newLine(sb); } ed.setFileComments(sb.toString()); } } /* * 初始化XML文件的根节点 */ public void initRootElement(XmlElement rootElement){ // just init the root element this.rootElement.set(rootElement); } /* * 清除XML文件的根节点 */ public void clearRootElement(){ this.rootElement.remove(); } @Override public void addRootComment(XmlElement rootElement) { // nothing have to do } public String getID(XmlElement xmlElement){ List<Attribute> attributes = xmlElement.getAttributes(); for(Attribute attribute : attributes){ if(attribute.getName().equalsIgnoreCase("id")){ return attribute.getValue(); } } return ""; } public void addBeforeSelfInParent(XmlElement self,String comment){ if(this.rootElement.get() == null) return; List<Element> elements = this.rootElement.get().getElements(); int selfIndex = elements.indexOf(self); if(selfIndex != -1){ // use block comments and limit the length of each line elements.add(selfIndex++, new TextElement("")); elements.add(selfIndex++, new TextElement("<!-- ")); if(comment.length() < 80){ elements.add(selfIndex++, new TextElement(" " + comment)); }else { do { String current = comment.substring(0, 80); elements.add(selfIndex++, new TextElement(" " + current)); comment = comment.substring(80); } while (comment.length() > 80); } elements.add(selfIndex++, new TextElement("-->")); } } /* * Adds a suitable comment to warn users that the element was generated, and * when it was generated. */ @Override public void addComment(XmlElement xmlElement) { if(suppressAllComments) return; String id = getID(xmlElement); // if user doesn't supply the specified comment the use the default String comment = comments.getString(id); if(StringUtils.isEmpty(comment)){ comment = defaultComments.getString(id); } if(StringUtils.isNotEmpty(comment)) { addBeforeSelfInParent(xmlElement, comment); } } @Override public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { if(suppressAllComments) return; // it's not beauty to add some no use comment to the method if(false) { StringBuilder sb = new StringBuilder(); method.addJavaDocLine("/*"); //$NON-NLS-1$ sb.append(" * created by XMBG"); //$NON-NLS-1$ if (!suppressDate) { sb.append(" on " + getDateString()); } else { sb.append("."); } method.addJavaDocLine(sb.toString()); method.addJavaDocLine(" */"); //$NON-NLS-1$ } } /* * This method adds the custom javadoc tag for. You may do nothing if you do * not wish to include the Javadoc tag - however, if you do not include the * Javadoc tag then the Java merge capability of the eclipse plugin will * break. * * @param javaElement the java element * @param markAsDoNotDelete */ @Override protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { //TODO just leave it for now } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { // no idea what to do } @Override public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { // no idea what to do } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { // no idea what to do } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable) { // no idea what to do } @Override public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { //there is no need to add comments } @Override public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { //there is no need to add comments } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { //TODO I have no idea what to say ? } }