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

src.com.github.aliteralmind.codelet.TemplateOverrides Maven / Gradle / Ivy

Go to download

**Codelet**: Automated insertion of *already unit-tested* example code (its source code, console output, and input text-files) into JavaDoc using inline taglets--Codelet makes it possible to have *always accurate documentation*.

There is a newer version: 0.1.4.1
Show newest version
/*license*\
   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)

   This software is dual-licensed under the:
   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
   - Apache Software License (ASL) version 2.0.

   Either license may be applied at your discretion. More information may be found at
   - http://en.wikipedia.org/wiki/Multi-licensing.

   The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package  com.github.aliteralmind.codelet;
   import  com.github.aliteralmind.codelet.type.ConsoleOutTemplate;
   import  com.github.aliteralmind.codelet.type.FileTextTemplate;
   import  com.github.aliteralmind.codelet.type.SourceAndOutTemplate;
   import  com.github.aliteralmind.codelet.type.SourceCodeTemplate;
   import  com.github.xbn.io.IOUtil;
   import  com.github.xbn.io.TextAppenter;
   import  com.github.xbn.lang.CrashIfObject;
   import  com.github.aliteralmind.templatefeather.FeatherTemplate;
   import  com.github.xbn.text.CrashIfString;
   import  java.util.HashMap;
   import  java.util.Iterator;
   import  java.util.Map;
   import  java.util.regex.Pattern;
   import  static com.github.aliteralmind.codelet.CodeletBaseConfig.*;
   import  static com.github.xbn.lang.XbnConstants.*;
/**
   

For optional overriding of default templates, for a single JavaDoc page or an entire package. For overriding a template in a single taglet, a customizer must be used.

Configuration is in a text file named {@linkplain CodeletBootstrap#TMPL_OVERRIDES_CONFIG_FILE_NAME template_overrides_config.txt}, which is located in the same directory as {@link com.github.aliteralmind.codelet.CodeletBaseConfig codelet.properties} (view {@code {@docRoot}/${jd_project_codelet_config_dir}/template_overrides_config.txt}). Loading is executed by {@link com.github.aliteralmind.codelet.CodeletBootstrap}.

If {@code template_overrides_config.txt} is empty (or contains only comments), then default templates are always used.

Each line is an override for either a specific JavaDoc file, or an entire package. It's format:

[fully-qualified-JavaDoc-file-name]     [codelet-type]     [relative-path-of-template-file]

Examples:

com.github.smith.overview-summary.html    SOURCE_CODE    overview_codelet_tmpl.txt
com.github.smith.overview-summary.html    SOURCE_AND_OUT   overview_codelet_and_out.txt
com.github.smith.sub.package              SOURCE_CODE    sub_packages\smith_pkg_codelet_tmpl.txt
com.github.smith.sub.package.AClass.java  CONSOLE_OUT   sub_packages\com_github_smith_overview_codelet_dot_out_tmpl.txt
com.github.smith.sub.package.AClass.java  FILE_TEXT      sub_packages\com_github_smith_overview_file_textlet_tmpl.txt

There are three columns, {@linkplain #SPLIT_PATTERN separated by} one-or-more tabs, or two-or-more spaces:

  1. {@code [fully-qualified-JavaDoc-file-name]}: The file or package to override.
  2. {@code [codelet-type]}: The {@linkplain CodeletType type} of codelet to override. Must equal "{@link com.github.aliteralmind.codelet.CodeletType#SOURCE_CODE SOURCE_CODE}", "{@link com.github.aliteralmind.codelet.CodeletType#CONSOLE_OUT CONSOLE_OUT}", "{@link com.github.aliteralmind.codelet.CodeletType#SOURCE_AND_OUT SOURCE_AND_OUT}", or "{@link com.github.aliteralmind.codelet.CodeletType#FILE_TEXT FILE_TEXT}".
  3. {@code [relative-path-of-template-file]}: The relative directory to the template file, as it exists in the user-template {@linkplain CodeletBaseConfig#USER_TEMPLATE_BASE_DIR base directory}.

Lines may be indented, and any lines starting with a hash ({@code '#'}) are ignored. Empty lines are also ignored.

Column one: {@code [fully-qualified-JavaDoc-file-name]}

Item type Example Description
An individual class {@code fully.qualified.AClass.java} Its fully-qualified class name, plus {@code ".java"}
The package summary page {@code fully.qualified.package-info.java}
{@code fully.qualified.package-summary.html}
It's fully-qualified name, including postfix, as it is read by the {@code javadoc} application (use the name of its source-file).
The overview summary page {@code overview-summary.html} The relative path of overview file, as it is configured into the {@code -overview} option.
An entire package {@code fully.qualified} The fully qualified package name. This only overrides classes directly in this package. No sub-packages are affected.

If both a file and its package are overridden, the individual file's override always takes precedence.

@since 0.1.0 @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. {@code http://codelet.aliteralmind.com}, {@code https://github.com/aliteralmind/codelet} **/ public enum TemplateOverrides { INSTANCE; private static boolean wasLoaded ; private static Map pkgMap ; private static Map fileMap ; /**

The pattern to split each line on (after it's trimmed)--Equal to {@link java.util.regex.Pattern Pattern}.{@link java.util.regex.Pattern#compile(String) compile}("(?:\\t|[ \\t]{2,})")

**/ public static final Pattern SPLIT_PATTERN = Pattern.compile("(?:\\t|[ \\t]{2,})"); /**

YYY

@exception IllegalStateException If
    {@link com.github.aliteralmind.codelet.CodeletTemplateConfig CodeletTemplateConfig}.{@link com.github.aliteralmind.codelet.CodeletTemplateConfig#wasLoaded() wasLoaded}
is {@code false}, or {@link #wasLoaded() wasLoaded}{@code ()} is {@code true}. **/ static final TemplateOverrides loadConfigGetInstance(Iterator configFile_lineItr) { if(!CodeletTemplateConfig.wasLoaded()) { throw new IllegalStateException("CodeletTemplateConfig.wasLoaded() is false."); } if(wasLoaded()) { throw new IllegalStateException("wasLoaded() is true."); } if(isDebugOn(null, "zzconfiguration.progress")) { debugln(" Loading template overrides config"); } pkgMap = new HashMap(500); fileMap = new HashMap(500); int lineNum = 1; try { while(configFile_lineItr.hasNext()) { processLine(lineNum++, configFile_lineItr.next()); } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(configFile_lineItr, "configFile_lineItr", null, rx); } if(isDebugOn(null, "zzconfiguration.progress")) { debugln(" - Template overrides:"); debugln(staticToString()); } wasLoaded = true; return INSTANCE; } /**

Was configuration loaded?.

@return {@code true} If all values loaded successfully. **/ public static final boolean wasLoaded() { return wasLoaded; } private static final void processLine(int line_num, String line) { line = line.trim(); boolean doDebug = isDebugOn(null, "zzconfiguration.templateoverrides.eachentryasloaded"); if(doDebug) { debugln(" [" + line_num + "] " + line); } if(line.startsWith("#") || line.length() == 0) { return; } String[] split = SPLIT_PATTERN.split(line.trim()); if(split.length != 3) { throw new TemplateOverridesConfigLineException(line_num, line, "Line contains " + split.length + " elements after splitting on \"" + SPLIT_PATTERN + "\"."); } String itemName = split[0]; CodeletType type = null; try { type = CodeletType.newTypeForTagletName(split[1], "[split line element index 1 (second element)]"); } catch(IllegalArgumentException iax) { throw new TemplateOverridesConfigLineException(line_num, line, "Element two is not a valid Codelet type", iax); } String path = getCustomTemplateDir() + split[2]; CodeletTemplateBase tmpl = newTemplateForTypeFromPath(type, path, line_num); if(itemName.endsWith(".html") || itemName.endsWith(".java")) { String nameNoDotExt = itemName.substring(0, itemName.length() - 5); if(doDebug) { debugln(" File exception"); } addLineItem(fileMap, nameNoDotExt, tmpl, line_num, line); } else { if(doDebug) { debugln(" Package exception"); } addLineItem(pkgMap, itemName, tmpl, line_num, line); } } private static final void addLineItem(Map item_map, String item_name, CodeletTemplateBase template, int line_num, String line) { if(item_map.containsKey(item_name)) { item_map.get(item_name).addTemplate(template, line_num, line); } else { item_map.put(item_name, new TemplateMapForFile(item_name, template, line_num, line)); } } /**

Get the template.

@return If this taglet's
  1. {@linkplain CodeletInstance#getEnclosingFile() enclosing file} has a template-override: The template as {@linkplain TemplateOverrides configured}
  2. {@linkplain CodeletInstance#getEnclosingPackage() enclosing package} has a template-override: The template as configured.
Otherwise, the default template for the taglet's {@linkplain CodeletType type}. In all cases, because JavaDoc is multi-threaded, the returned template object is duplicated. @exception IllegalArgumentStateException If the enclosing file's path does not start with the enclosing class {@linkplain CodeletBaseConfig#ENCLOSING_CLASS_SRC_BASE_DIRS base directory}. **/ public static final T get(CodeletInstance instance, Appendable debugDest_ifNonNull) { String itemName = null; try { if(!instance.isOverviewSummary()) { //According to the user, this uses getEnclosingBaseDirList(). //We're actually using getEnclosingBaseDirs(), which is to //avoid translating the list to an array each time. itemName = IOUtil.getRelativePathCrashIfBadBaseDir(instance.getEnclosingFile().getPath(), "instance.getEnclosingFile().getPath()", "getEnclosingBaseDirList()", getEnclosingBaseDirs()). replace(FILE_SEP, "."); } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(instance, "instance", null, rx); } boolean doDebug = isDebugOn(null, "zzTemplateOverrides.getresult"); if(doDebug) { debugln(" TemplateOverrides.get: " + itemName + ", type: " + instance.getType()); } CodeletTemplateBase tmpl = null; try { if(fileMap.containsKey(itemName)) { TemplateMapForItem tpmlForItem = fileMap.get(itemName); if(doDebug) { debugln(" File override " + tpmlForItem); } tmpl = tpmlForItem.getDuplicatedTemplateOfType(instance.getType(), debugDest_ifNonNull); } else if(pkgMap.containsKey(itemName)) { // tmpl = pkgMap.get(itemName).getDuplicatedTemplateOfType(instance.getType(), debugDest_ifNonNull); TemplateMapForItem tpmlForItem = pkgMap.get(itemName); if(doDebug) { debugln(" Package override " + tpmlForItem); } tmpl = tpmlForItem.getDuplicatedTemplateOfType(instance.getType(), debugDest_ifNonNull); } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(instance, "instance", null, rx); } if(tmpl == null) { if(doDebug) { debugln(" No override. Returning default template."); } if(instance.getType().isSourceCode()) { tmpl = CodeletTemplateConfig.getDefaultSourceCodeTemplate(). getObjectCopy(debugDest_ifNonNull); } if(instance.getType().isConsoleOut()) { tmpl = CodeletTemplateConfig.getDefaultConsoleOutTemplate(). getObjectCopy(debugDest_ifNonNull); } if(instance.getType().isSourceAndOut()) { tmpl = CodeletTemplateConfig.getDefaultSourceAndOutTemplate(). getObjectCopy(debugDest_ifNonNull); } if(instance.getType().isFileText()) { tmpl = CodeletTemplateConfig.getDefaultFileTextTemplate(). getObjectCopy(debugDest_ifNonNull); } } @SuppressWarnings("unchecked") T t = (T)tmpl; if(doDebug) { debugln(" Returning template: " + t.getPath()); } return t; } @SuppressWarnings("unchecked") private static final T newTemplateForTypeFromPath(CodeletType type, String path, int line_num) { CodeletTemplateBase tmplBase = null; String lineNumDesc = "TemplateOverrides configuration file, line " + line_num; try { switch(type) { case SOURCE_CODE: tmplBase = SourceCodeTemplate.newFromPathAndUserExtraGaps(path, lineNumDesc, CodeletTemplateConfig.getUserExtraGapsClass()); break; case CONSOLE_OUT: tmplBase = ConsoleOutTemplate.newFromPathAndUserExtraGaps(path, lineNumDesc, CodeletTemplateConfig.getUserExtraGapsClass()); break; case SOURCE_AND_OUT: tmplBase = SourceAndOutTemplate.newFromPathAndUserExtraGaps(path, lineNumDesc, CodeletTemplateConfig.getUserExtraGapsClass()); break; case FILE_TEXT: tmplBase = FileTextTemplate.newFromPathAndUserExtraGaps(path, lineNumDesc, CodeletTemplateConfig.getUserExtraGapsClass()); break; default: throw new IllegalStateException("Unknown type: template.getType()=" + type); } } catch(RuntimeException rx) { throw CrashIfObject.nullOrReturnCause(type, "type", null, rx); } @SuppressWarnings("unchecked") T t = (T)tmplBase; return t; } public static final String staticToString() { return appendStaticToString(new StringBuilder()).toString(); } public static final StringBuilder appendStaticToString(StringBuilder to_appendTo) { to_appendTo.append("File overrides (" + fileMap.size() + " total)"); boolean doDebug = isDebugOn(null, "zzconfiguration.templateoverrides.allentriespostloaded"); if(doDebug) { to_appendTo.append(":").append(LINE_SEP); for (Map.Entry entry : fileMap.entrySet()) { entry.getValue().appendToString(to_appendTo); } } else { to_appendTo.append(LINE_SEP); } to_appendTo.append("Package overrides (" + pkgMap.size() + " total)"); if(doDebug) { to_appendTo.append(":").append(LINE_SEP); for (Map.Entry entry : pkgMap.entrySet()) { entry.getValue().appendToString(to_appendTo); } } return to_appendTo; } } class TemplateMapForItem { private String itemName; public SourceCodeTemplate scTmpl ; public ConsoleOutTemplate coTmpl; public SourceAndOutTemplate saoTmpl; public FileTextTemplate ftTmpl ; public TemplateMapForItem(String item_name, CodeletTemplateBase first_tmpl, int line_num, String line) { CrashIfString.nullEmpty(item_name, "item_name", null); itemName = item_name; addTemplate(first_tmpl, line_num, line); } public String getItemName() { return itemName; } public CodeletTemplateBase getDuplicatedTemplateOfType(CodeletType type, Appendable debugDest_ifNonNull) { switch(type) { case SOURCE_CODE: return (new SourceCodeTemplate(scTmpl, debugDest_ifNonNull)); case CONSOLE_OUT: return (new ConsoleOutTemplate(coTmpl, debugDest_ifNonNull)); case SOURCE_AND_OUT: return (new SourceAndOutTemplate(saoTmpl, debugDest_ifNonNull)); case FILE_TEXT: return (new FileTextTemplate(ftTmpl, debugDest_ifNonNull)); default: throw new IllegalStateException("Unknown type: " + type); } } @SuppressWarnings("unchecked") public void addTemplate(CodeletTemplateBase template, int line_num, String line) { CodeletType type = template.getType(); switch(type) { case SOURCE_CODE: scTmpl = TemplateMapForItem.getParamTmplOrCrashIfAlreadySet (this, scTmpl, (SourceCodeTemplate)template, line_num, line); break; case CONSOLE_OUT: coTmpl = TemplateMapForItem.getParamTmplOrCrashIfAlreadySet (this, coTmpl, (ConsoleOutTemplate)template, line_num, line); break; case SOURCE_AND_OUT: saoTmpl = TemplateMapForItem.getParamTmplOrCrashIfAlreadySet (this, saoTmpl, (SourceAndOutTemplate)template, line_num, line); break; case FILE_TEXT: ftTmpl = TemplateMapForItem.getParamTmplOrCrashIfAlreadySet (this, ftTmpl, (FileTextTemplate)template, line_num, line); break; default: throw new IllegalStateException("Unknown type: template.getType()=" + type); } } private static final T getParamTmplOrCrashIfAlreadySet(TemplateMapForItem map_forItem, T class_tmpl, T param_tmpl, int line_num, String line) { if(class_tmpl != null) { throw new TemplateOverridesConfigLineException(line_num, line, "Template of type " + param_tmpl.getType() + " type already set for " + map_forItem.getItemName()); } return param_tmpl; } public String toString() { return appendToString(new StringBuilder()).toString(); } public StringBuilder appendToString(StringBuilder to_appendTo) { to_appendTo.append(" ").append(getItemName()).append(LINE_SEP); appendTypeToString(to_appendTo, scTmpl); appendTypeToString(to_appendTo, coTmpl); appendTypeToString(to_appendTo, saoTmpl); appendTypeToString(to_appendTo, ftTmpl); return to_appendTo; } public StringBuilder appendTypeToString(StringBuilder to_appendTo, CodeletTemplateBase tmpl) { return ((scTmpl == null) ? to_appendTo : to_appendTo.append(" - ").append(scTmpl.getType()).append(": ").append(scTmpl.getPath())).append(LINE_SEP); } } class TemplateMapForPackage extends TemplateMapForItem { public TemplateMapForPackage(String item_name, CodeletTemplateBase first_tmpl, int line_num, String line) { super(item_name, first_tmpl, line_num, line); if(item_name.endsWith(".html")) { throw new TemplateOverridesConfigLineException(line_num, line, "Not a package (ends with \".html\")"); } } } class TemplateMapForFile extends TemplateMapForItem { public TemplateMapForFile(String item_name, CodeletTemplateBase first_tmpl, int line_num, String line) { super(item_name, first_tmpl, line_num, line); if(item_name.endsWith(".html")) { throw new TemplateOverridesConfigLineException(line_num, line, "Not a file (does not end with \".html\")"); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy