001/*license*\
002   Codelet: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
003
004   This software is dual-licensed under the:
005   - Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
006   - Apache Software License (ASL) version 2.0.
007
008   Either license may be applied at your discretion. More information may be found at
009   - http://en.wikipedia.org/wiki/Multi-licensing.
010
011   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:
012   - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
013   - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
014\*license*/
015package  com.github.aliteralmind.codelet;
016   import  com.github.aliteralmind.codelet.alter.DefaultAlterGetter;
017   import  com.github.aliteralmind.codelet.alter.DefaultDefaultAlterGetter;
018   import  com.github.aliteralmind.codelet.util.AllOnlineOfflineDocRoots;
019   import  com.github.aliteralmind.codelet.util.FilenameBlackWhiteList;
020   import  com.github.aliteralmind.codelet.util.NamedDebuggers;
021   import  com.github.aliteralmind.codelet.util.RefreshOffline;
022   import  com.github.aliteralmind.templatefeather.GapCharConfig;
023   import  com.github.xbn.io.AppendOrOverwrite;
024   import  com.github.xbn.io.DebugLevel;
025   import  com.github.xbn.io.NewTextAppenterFor;
026   import  com.github.xbn.io.PathMustBe;
027   import  com.github.xbn.io.TextAppenter;
028   import  com.github.xbn.lang.CrashIfObject;
029   import  com.github.xbn.lang.Empty;
030   import  com.github.xbn.lang.reflect.ReflectRtxUtil;
031   import  com.github.xbn.list.MapUtil;
032   import  com.github.xbn.util.IfError;
033   import  com.github.xbn.util.PropertiesUtil;
034   import  java.io.IOException;
035   import  java.net.MalformedURLException;
036   import  java.nio.file.AccessDeniedException;
037   import  java.nio.file.NoSuchFileException;
038   import  java.nio.file.Paths;
039   import  java.util.Arrays;
040   import  java.util.Collections;
041   import  java.util.Iterator;
042   import  java.util.List;
043   import  java.util.Map;
044   import  java.util.Properties;
045   import  java.util.regex.Matcher;
046   import  java.util.regex.Pattern;
047   import  static com.github.xbn.lang.XbnConstants.*;
048/**
049   <p>Immutable, static, and non-template related configuration, used throughout Codelet, as held in a file named {@link CodeletBootstrap#BASE_CONFIG_FILE_NAME codelet.properties}. Loading is executed by {@link com.github.aliteralmind.codelet.CodeletBootstrap}.</p>
050
051   <p><i>View <a href="{@docRoot}/../codelet_config/codelet.properties">{@code {@docRoot}/../codelet_config/codelet.properties}</a>.)</i></p>
052
053   <A NAME="base_dirs_other"></a><h2><a href="{@docRoot}/overview-summary.html#overview_description"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; <u>Codelet: Configuration</u></h2>
054
055   <p><i>See <a href="{@docRoot}/overview-summary.html#install_configure">getting started</a> in the Codelet installation instructions.</i></p>
056
057   <p>There are four categories of Codelet global configuration:<ul>
058      <li><a href="#base_dirs_other">Base directories</a> and other</li>
059      <li><a href="#tmpl_defaults">Default templates</a></li>
060      <li><a href="#tmpl_gaps">Template gaps</a></li>
061      <li><a href="#debugging">Debugging and diagnostics</a></li>
062   </ul></p>
063
064   <A NAME="base_dirs_other"></a><h2><a href="CodeletBaseConfig.html"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; Codelet: Configuration: <u>Base directories and urls, and other</u></h2>
065
066   <p><TABLE ALIGN="center" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
067      <TD>&nbsp;</TD>
068      <TD><b><u>Name</u></b></TD>
069      <TD><b><u>Description</u></b></TD>
070   </TR><TR>
071      <TD>&nbsp;</TD>
072      <TD>{@link #BASE_DIR_BASE_DIR base_dir_base_dir}</TD>
073      <TD>For use in all other &quot;base_dir&quot; config vars, with &quot;${BASE}&quot;</TD>
074   </TR><TR>
075      <TD>{@linkplain #getExampleSourceBaseDir() func}</TD>
076      <TD>{@link #EXAMPLE_CLASS_SRC_BASE_DIR example_class_src_base_dir}</TD>
077      <TD>Directory containing the top-most package for the source code of all example classes.</TD>
078   </TR><TR>
079      <TD>{@linkplain #getEnclosingBaseDirList() func}</TD>
080      <TD>{@link #ENCLOSING_CLASS_SRC_BASE_DIRS enclosing_class_src_base_dirs}</TD>
081      <TD>Comma-separated list of all directories containing the <i>top-most package-directories</i> of all codelet-containing source files.</TD>
082   </TR><TR>
083      <TD>{@linkplain #getDefaultAlterGetter() func}</TD>
084      <TD>{@link #DEFAULT_ALTERERS_CLASS_NAME default_alterers_class_name}</TD>
085      <TD>Fully-qualified name of the class that defines alterers used by all pre-built customizers, and are accessible in custom customizers.</TD>
086   </TR></TABLE></p>
087
088   <A NAME="tmpl_javadoc"></a><h2><a href="CodeletBaseConfig.html"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; Codelet: Configuration: <u>JavaDoc related</u></h2>
089
090   <p><TABLE ALIGN="center" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
091      <TD><b><u>Func</u></b></TD>
092      <TD><b><u>Name</u></b></TD>
093      <TD><b><u>Description</u></b></TD>
094   </TR><TR>
095      <TD>{@link #getTargetClassMapInitCapacity() func}</TD>
096      <TD>{@link #UNIQUE_JD_CLASS_TARGET_INIT_CAPACITY unique_jd_class_target_init_capacity}</TD>
097      <TD>Initial capacity of the map holding the JavaDoc target-class shortcut translators.</TD>
098   </TR><TR>
099      <TD>{@link #getOnlinePackageListAttemptCount() func}</TD>
100      <TD>{@link #PKGLIST_ONLINE_ATTEMPT_COUNT pkglist_online_attempts_per_url}</TD>
101      <TD>How many attempts should be made to retrieve each online package-list? If zero, offline only.</TD>
102   </TR><TR>
103      <TD>{@link #getOnlinePackageListAttemptSleepMills() func}</TD>
104      <TD>{@link #PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS pkglist_online_attempt_sleep_mills}</TD>
105      <TD>How many milliseconds between each failed attempt?</TD>
106   </TR><TR>
107      <TD>{@link #doCrashIfOnlinePackageListFailure() func}</TD>
108      <TD>{@link #PKGLIST_ONLINE_FAILS_BEHAVIOR pkglist_if_online_retrieval_fails__warn_crash}</TD>
109      <TD>If all online-retrieval attempts fail, should only a warning be logged, or should Codelet stop execution? (Offline package-lists are always retrieved.)</TD>
110   </TR><TR>
111      <TD>{@link #doAutoUpdateOfflinePackageLists() func}</TD>
112      <TD>{@link #AUTO_UPDATE_OFFLINE_PACKAGE_LISTS pkglist_auto_refresh_offline__yes_no}</TD>
113      <TD>When online package-lists are retrieved, should offline package lists be refreshed (or created)?</TD>
114   </TR><TR>
115      <TD>{@link #getOfflinePackageListPostfix() func}</TD>
116      <TD>{@link #PKGLIST_OFFLINE_NAME_POSTFIX pkglist_offline_name_postfix}</TD>
117      <TD>Filename postfix, plus optional dot-extension that follows each offline name.</TD>
118   </TR></TABLE></p>
119
120   <A NAME="tmpl_defaults"></a><h2><a href="CodeletBaseConfig.html"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; Codelet: Configuration: <u>Default template files</u></h2>
121
122   <p><TABLE ALIGN="center" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
123      <TD><b><u>Func</u></b></TD>
124      <TD><b><u>Name</u></b></TD>
125      <TD><b><u>Description</u></b></TD>
126   </TR><TR>
127      <TD>&nbsp;</TD>
128      <TD>{@link #DEFAULT_TPML_DIR_PREFIX default_template_directory_prefix}</TD>
129      <TD>Prepended to all {@code "default_*_template_path"} values.</TD>
130   </TR><TR>
131      <TD>{@linkplain #getDefaultSourceCodeTemplatePath() func}</TD>
132      <TD>{@link #DEFAULT_SRC_CODE_TMPL_PATH default_source_codelet_template_path}</TD>
133      <TD>Path to the (source-code) {@link CodeletType#SOURCE_CODE {@.codelet}} taglet's default template.</TD>
134   </TR><TR>
135      <TD>{@linkplain #getDefaultConsoleOutTemplatePath() func}</TD>
136      <TD>{@link #DEFAULT_DOT_OUT_TMPL_PATH default_dot_out_template_path}</TD>
137      <TD>Path to the {@link CodeletType#CONSOLE_OUT {@.codelet.out}} taglet's default template.</TD>
138   </TR><TR>
139      <TD>{@linkplain #getDefaultFileTextTemplatePath() func}</TD>
140      <TD>{@link #DEFAULT_FILE_TEXT_TMPL_PATH default_file_textlet_template_path}</TD>
141      <TD>Path to the default template used for the {@link CodeletType#FILE_TEXT {@.file.textlet}} taglet's default template.</TD>
142   </TR><TR>
143      <TD>{@linkplain #getDefaultSourceAndOutTemplatePath() func}</TD>
144      <TD>{@link #DEFAULT_AND_OUT_TMPL_PATH default_and_out_template_path}</TD>
145      <TD>Path to the {@link CodeletType#SOURCE_AND_OUT {@.codelet.and.out}} taglet's default template.</TD>
146   </TR><TR>
147      <TD>{@linkplain #getCustomTemplateDir() func}</TD>
148      <TD>{@link #USER_TEMPLATE_BASE_DIR user_template_base_dir}</TD>
149      <TD>Directory in which any custom (user-created) templates are stored.</TD>
150   </TR></TABLE></p>
151
152   <A NAME="tmpl_gaps"></a><h2><a href="CodeletBaseConfig.html"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; Codelet: Configuration: <u>Template gaps</u></h2>
153
154   <p><TABLE ALIGN="center" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
155      <TD><b><u>Func</u></b></TD>
156      <TD><b><u>Name</u></b></TD>
157      <TD><b><u>Description</u></b></TD>
158   </TR><TR>
159      <TD>{@linkplain #getGapCharConfig() func}</TD>
160      <TD>{@link #GAP_NAME_PREFIX_CHAR gap_name_prefix_char}</TD>
161      <TD>Character placed immediately before all template gap names.</TD>
162   </TR><TR>
163      <TD>&nbsp;</TD>
164      <TD>{@link #GAP_NAME_POSTFIX_CHAR gap_name_postfix_char}</TD>
165      <TD>Character placed immediately after gap names.</TD>
166   </TR><TR>
167      <TD>&nbsp;</TD>
168      <TD>{@link #GAP_NAME_LITERAL_PREFIX gap_literal_prefix_char}</TD>
169      <TD>Literal representation of the prefix char, for use in between texts.</TD>
170   </TR><TR>
171      <TD>&nbsp;</TD>
172      <TD>{@link #GAP_NAME_LITERAL_POSTFIX gap_literal_name_postfix_char}</TD>
173      <TD>Literal representation of the postfix char, for use in between texts.</TD>
174   </TR><TR>
175      <TD>{@linkplain #getUserExtraGapsClassName() func}</TD>
176      <TD>{@link #USER_EXTRA_GAPS_CLASS_NAME user_extra_gaps_class}</TD>
177      <TD>Fully-qualified name of the class that defines extra gaps that can be placed in Codelet templates.</TD>
178   </TR></TABLE></p>
179
180
181
182   <A NAME="debugging"></a><h2><a href="CodeletBaseConfig.html"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a> &nbsp; Codelet: Configuration: <u>Debugging and diagnostics</u></h2>
183
184   <p><TABLE ALIGN="center" BORDER="1" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#EEEEEE"><TR ALIGN="center" VALIGN="middle">
185      <TD><b><u>Func</u></b></TD>
186      <TD><b><u>Name</u></b></TD>
187      <TD><b><u>Description</u></b></TD>
188   </TR><TR>
189      <TD>{@linkplain #getGlobalDebugLevel() func}</TD>
190      <TD>{@link #GLOBAL_DEBUG_LEVEL global_debugging__off_12345}</TD>
191      <TD>Amount that information that should be logged in every taglet-call</TD>
192   </TR><TR>
193      <TD>{@linkplain #getDebugAptr() func}</TD>
194      <TD>{@link #DEBUG_DESTINATION debug_to__console_path}</TD>
195      <TD>If debugging is on, where should it be written to?</TD>
196   </TR><TR>
197      <TD>{@linkplain #getBlackWhiteList() func}</TD>
198      <TD>{@link #BLACK_WHITE_LIST_TYPE list_type__black_white_off}</TD>
199      <TD>For ignoring all codelets in a single file, or in an entire package.</TD>
200   </TR><TR>
201      <TD>&nbsp;</TD>
202      <TD>{@link #BLACK_WHITE_LIST_CASE list_case__ignore_require_system}</TD>
203      <TD>When comparing class names against the black/white list, how should case be considered?.</TD>
204   </TR><TR>
205      <TD>&nbsp;</TD>
206      <TD>{@link #BLACK_WHITE_PROPER_LIST comma_delimited_proper_list}</TD>
207      <TD>List of wildcard matches that determine which files or packages should be recognized.</TD>
208   </TR><TR>
209      <TD>&nbsp;</TD>
210      <TD>{@link #BLACK_WHITE_OVERRIDE_LIST comma_delimited_override_list}</TD>
211      <TD>List of wildcard matches that trump those in the &quot;proper&quot;-list.</TD>
212   </TR><TR>
213      <TD>{@link #doCrashIfAlterationNotMade() func}</TD>
214      <TD>{@link #ALTERATION_NOT_MADE_CRASH if_alteration_not_made_crash__yes_no}</TD>
215      <TD>If a customizer attempts to make an alteration, but cannot (such as when the find-what text is not found in the example code), should a crash occur, in addition to the warning?</TD>
216   </TR></TABLE></p>
217
218 * @since  0.1.0
219 * @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. <a href="http://codelet.aliteralmind.com">{@code http://codelet.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/codelet">{@code https://github.com/aliteralmind/codelet}</a>
220 **/
221public enum CodeletBaseConfig  {
222   INSTANCE;
223   private static boolean       wasLoaded                 ;
224   private static DebugLevel    dbgLevel                  ;
225   private static TextAppenter  dbgAptr                   ;
226   private static boolean       doDebugToConsole          ;
227   private static GapCharConfig gapCharConfig             ;
228   private static String        xmplSrcBaseDir            ;
229   private static String[]      enclosingBaseDirs         ;
230   private static List<String>  enclosingBaseDirList      ;
231   private static DefaultAlterGetter defaultAlterGetter   ;
232   private static String        customTmplDir             ;
233   private static String        defaultSrcTmplPath        ;
234   private static String        defaultOutTmplPath        ;
235   private static String        defaultSrcAndOutTmplPath  ;
236   private static String        defaultFileTextTmplPath   ;
237   private static String        userExtraGapsClassNm      ;
238   private static FilenameBlackWhiteList blackWhiteList   ;
239   private static int           jdTgtClsMapInitCapacity   ;
240   private static boolean       doCrashIfAlterNotMade     ;
241   private static AllOnlineOfflineDocRoots allDocRoots    ;
242   private static int           onlinePkgLstAttemptCount  ;
243   private static long          onlinePkgLstAttemptSleepMills;
244   private static boolean       doCrashIfOnlinePkgLstFails;
245   private static boolean       doAutoUpdateOfflinePkgLsts;
246   private static String        offlinePkgLstNamePost     ;
247   private static NamedDebuggers namedDebugLevels       ;
248
249   /**
250      <p>Default value for {@code pkglist_online_attempts_per_url} when not provided--Equal to {@code 5}.</p>
251
252    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
253    */
254   public static final int DEFAULT_ONLINE_PKGLST_ATTEMPTS = 5;
255   /**
256      <p>Default value for {@code pkglist_online_attempts_per_url} when not provided--Equal to {@code 500}.</p>
257
258    * @see  #PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS
259    */
260   public static final int DEFAULT_ONLINE_PKGLST_SLEEP_MILLS = 500;
261   /**
262      <p>Default value for {@code unique_jd_class_target_init_capacity} when not provided--Equal to {@code 100}.</p>
263
264    * @see  #UNIQUE_JD_CLASS_TARGET_INIT_CAPACITY
265    */
266   public static final int DEFAULT_JD_TARGET_CLASS_MAP_INIT_CAPACITY = 100;
267   /*
268      <p>Should the {@linkplain CodeletBootstrap#EXTERNAL_DOC_ROOT_URL_FILE offline versions} of external library {@code package-list} files be automatically updated?--Equal to {@code "pkglist_auto_refresh_offline__yes_no"}.</p>
269
270      <p>Must be one of two values:<ul>
271         <li>{@code "yes"}: Every execution of {@code javadoc.exe} updates the offline files to equal the most recent content of their online counterparts.</li>
272         <li>{@code "no"}: Offline files must be manually (created and) updated. If they do not exist, an error occurs.</li>
273      </ul></p>
274
275    * @see  #doAutoUpdateOfflinePackageLists()
276   public static final String AUTO_UPDATE_OFFLINE_PACKAGE_LISTS = "pkglist_auto_refresh_offline__yes_no";
277    */
278
279   /**
280      <p>Directory containing the top-most package for the source code of all example classes--Name is {@code "example_class_src_base_dir"}.</p>
281
282      <p>If this is an example code</p>
283
284      <p><code>com.github.smith.examples.AGoodExample</code></p>
285
286      <p>and the path to its source code is</p>
287
288      <p>{@code C:\java_code\com\github\smith\examples\AGoodExample.java}</p>
289
290      <p>set this to</p>
291
292      <p>{@code "C:\java_code\"}</p>
293
294      <p>The ending file-separator is requried. This may or may not be equal to {@link #ENCLOSING_CLASS_SRC_BASE_DIRS}. And its value may include the &quot;{@link #BASE_DIR_BASE_DIR base_dir_base_dir}&quot;.</p>
295
296    * @see  <code><a href="#base_dirs_other"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
297    * @see  #getExampleSourceBaseDir()
298    */
299   public static final String EXAMPLE_CLASS_SRC_BASE_DIR = "example_class_src_base_dir";
300   /**
301      <p>For ignoring all codelets in a single file, or in an entire package--Name is {@code "list_type__black_white_off"}.</p>
302
303      <p><i>({@linkplain #GLOBAL_DEBUG_LEVEL Debugging Codelet} in general)</i></p>
304
305      <p><ul>
306         <li>{@code list_type__black_white_off}: Must be one of the following:<ul>
307            <li>{@code "black"}: The codelets in any files or packages that match an item in the proper-list, are ignored. Those not matched are processed.</li>
308            <li>{@code "white"}: The codelets in any files or packages that match an item in the proper-list, are processed.</li>
309            <li>{@code "off"}: All codelets are processed.</li>
310         </ul></li>
311         <li>{@code list_case__ignore_require_system}: When comparing the fully-qualified name of the enclosing file (or package), should letter case be considered?<ul>
312            <li>{@code "ignore"}: Case {@linkplain org.apache.commons.io.IOCase#INSENSITIVE insensitive}</li>
313            <li>{@code "require"}: Case ({@linkplain org.apache.commons.io.IOCase#SENSITIVE sensitive})</li>
314            <li>{@code "system"}: Case sensitivity is determined by the ({@linkplain org.apache.commons.io.IOCase#SYSTEM operating system})</li>
315         </ul></li>
316         <li>{@code comma_delimited_proper_list}: The list of wildcard matches that, when the fully-qualified file or package is matched, are ignored or processed (as determined by the black/white setting). Whitelist examples:<ul>
317            <li>To process all codelets in all packages: {@code "*"}</li>
318            <li>To process codelets only in a single package: {@code "github.com.myname.text.*"}</li>
319            <li>To process codelets in one package, plus a subset of files in another: {@code "github.com.myname.text.*,github.com.myname.io.Get*ForPath"}</li>
320         </ul>Do not put any dot-postfix after the file names (such as {@code ".java"} or {@code ".html"}). <i>For the overview summary ({@code "overview-summary.html"}), use {@code "OVERVIEW_SUMMARY"}. For package summary's ({@code "package-info.java"} or {@code "package-summary.html"}), use {@code "PACKAGE_SUMMARY"}.</i></li>
321         <li>{@code comma_delimited_override_list}: The list of wildcard matches that trump those in the proper-list. This list is only applicable when a file or package is matched by a proper-item. Examples:<ul>
322            <li>To process all codelets except those in a single file, using a whitelist (the value of {@code list_case__ignore_require_system} is required, but left out of these examples):
323
324<blockquote><pre>list_type__black_white_off=white
325comma_delimited_proper_list=fully.qualified.class.name.of.FileToProcess
326comma_delimited_override_list=</pre></blockquote></li>
327            <li>Using a blacklist:
328<blockquote><pre>list_type__black_white_off=black
329comma_delimited_proper_list=*
330comma_delimited_override_list=*.FileToProcess</pre></blockquote></li>
331            <li>To process codelets only in a single package: {@code "github.com.myname.text.*"}</li>
332            <li>To process codelets in one package, plus a subset of files in another: {@code "github.com.myname.text.*,github.com.myname.io.Get*ForPath"}</li>
333         </ul>Asterisks ({@code '*'}) indicate one-or-more of any character, and question marks ({@code '?'}) mean exactly one of any character. So, if {@code FileToProcess} is a unique filename across all project directories {@code comma_delimited_proper_list} could alternatively be
334      <br/> &nbsp; &nbsp; {@code *.FileToProcess}
335      <br/>If it is not unique:
336      <br/> &nbsp; &nbsp; {@code *.name.of.FileToProcess}</li>
337      </ul>These values are processed by <code>{@link com.github.aliteralmind.codelet.util.FilenameBlackWhiteList FilenameBlackWhiteList}.{@link com.github.aliteralmind.codelet.util.FilenameBlackWhiteList#newFromConfigStringVars(String, String, String, String, String, Appendable, Appendable) newFromConfigStringVars}</code></p>
338
339    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
340    * @see  com.github.aliteralmind.codelet.util.FilenameBlackWhiteList
341    * @see  #getBlackWhiteList()
342    * @see  #BLACK_WHITE_LIST_CASE
343    * @see  #BLACK_WHITE_PROPER_LIST
344    * @see  #BLACK_WHITE_OVERRIDE_LIST
345    */
346   public static final String BLACK_WHITE_LIST_TYPE = "list_type__black_white_off";
347   /**
348      <p>If a customizer attempts to make an alteration, but cannot (such as when the find-what text is not found in the example code), should a crash occur, in addition to the warning?--Name is {@code "if_alteration_not_made_crash__yes_no"}.</p>
349
350      <p>Must be one of two values:<ul>
351         <li>{@code "no"}: Only warnings will be logged.</li>
352         <li>{@code "yes"}: In addition to the warning, and exception is thrown.</li>
353      </ul></p>
354
355    * @see  #doCrashIfAlterationNotMade()
356    * @see  com.github.aliteralmind.codelet.alter.NewJDLinkForWordOccuranceNum
357    * @see  CustomizationInstructions#getCustomizedBody(CodeletInstance, Iterator) CustomizationInstructions#getCustomizedBody
358    */
359   public static final String ALTERATION_NOT_MADE_CRASH = "if_alteration_not_made_crash__yes_no";
360
361   /**
362      <p>Initial capacity of the map holding the JavaDoc target-class shortcut translators--Name is {@code "unique_jd_class_target_init_capacity"}. When not provided (set to the empty-string: {@code ""}), this defaults to {@link #DEFAULT_JD_TARGET_CLASS_MAP_INIT_CAPACITY}.</p>
363
364    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
365    * @see  com.github.aliteralmind.codelet.alter.NewJDLinkForWordOccuranceNum#getAllParamSigsForLinkTarget(Class)
366    * @see  #getTargetClassMapInitCapacity()
367    */
368   public static final String UNIQUE_JD_CLASS_TARGET_INIT_CAPACITY = "unique_jd_class_target_init_capacity";
369   /**
370      <p>When comparing class names against the black/white list, how should case be considered?--Name is {@code "list_case__ignore_require_system"}.</p>
371
372    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
373    * @see  #BLACK_WHITE_LIST_TYPE
374    */
375   public static final String BLACK_WHITE_LIST_CASE = "list_case__ignore_require_system";
376   /**
377      <p>List of wildcard matches that determine which files or packages should be recognized--Name is {@code "comma_delimited_proper_list"}.</p>
378
379    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
380    * @see  #BLACK_WHITE_LIST_TYPE
381    */
382   public static final String BLACK_WHITE_PROPER_LIST = "comma_delimited_proper_list";
383   /**
384      <p>List of wildcard matches that trump those in the &quot;proper&quot;-list--Name is {@code "comma_delimited_proper_list"}.</p>
385
386    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
387    * @see  #BLACK_WHITE_LIST_TYPE
388    */
389   public static final String BLACK_WHITE_OVERRIDE_LIST = "comma_delimited_override_list";
390   /**
391      <p>Comma-separated list of all directories containing the <i>top-most package-directory</i> of all codelet-containing source files--Name is {@code "enclosing_class_src_base_dirs"}.</p>
392
393      <p>If all codelet-containing source code exists in a single directory:</p>
394
395<blockquote><pre>C:\java_code\src\project_overview.html
396C:\java_code\src\com\github\xbn\lang\AClass.java
397C:\java_code\src\com\github\xbn\examples\lang\Demo_AClass.java
398C:\java_code\src\com\github\xbn\examples\test\UnitTest_AClass.java</pre></blockquote>
399
400      <p>Then set this to {@code "C:\java_code\src\"}</p>
401
402      <p>If there are multiple directories:</p>
403
404<blockquote><pre>C:\java_code\supplemental_files\project_overview.html
405C:\java_code\src\com\github\xbn\lang\AClass.java
406C:\java_code\src\com\github\xbn\examples\lang\Demo_AClass.java
407C:\java_code\src\com\github\xbn\examples\test\UnitTest_AClass.java</pre></blockquote>
408
409      <p>Then use
410      <br/> &nbsp; &nbsp; {@code C:\java_code\src\,C:\java_code\supplemental_files\}
411      <br/>or set &quot;{@link #BASE_DIR_BASE_DIR base_dir_base_dir}&quot; to {@code "C:\java_code\"}, and use
412      <br/> &nbsp; &nbsp; {@code ${BASE}src\,${BASE}supplemental_files\}</p>
413
414      <p><b>At least one directory-value is required.</b></p>
415
416      <p>The project-overview file, as <a href="http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javadoc.html#overview">configured</a> into JavaDoc, must exist in one of these directories. If its path is
417      <br/> &nbsp; &nbsp; {@code C:\java_code\src\project_overview.html}
418      <br/>and {@code C:\java_code\src\} is its enclosing class base-directory, then its fully-qualified name as required by the {@linkplain #BLACK_WHITE_LIST_TYPE blacklist} is {@code "project_overview"}. And in the hand {@linkplain TemplateOverrides template-overrides} configuration file, it is {@code "project_overview.html"}.</p>
419
420      <p>This value may be equal to (or contain) {@link #EXAMPLE_CLASS_SRC_BASE_DIR}.</p>
421
422    * @see  <code><a href="#base_dirs_other"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
423    * @see  #BASE_DIR_BASE_DIR
424    * @see  #getEnclosingBaseDirList()
425    */
426   public static final String ENCLOSING_CLASS_SRC_BASE_DIRS = "enclosing_class_src_base_dirs";
427   /**
428      <p>For use in all other &quot;base_dir&quot; config vars, with &quot;${BASE}&quot;--Name is {@code "base_dir_base_dir"}.</p>
429
430      <p>Only the first use is recognized. If this variable equals
431      <br/> &nbsp; &nbsp; <code>C:\java_code\</code>
432      <br/>then
433      <br/> &nbsp; &nbsp; <code>${BASE}hello${BASE}</code>
434      <br/>is translated to
435      <br/> &nbsp; &nbsp; <code>C:\java_code\hello${BASE}</code></p>
436
437    * @see  <code><a href="#base_dirs_other"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
438    * @see  #ENCLOSING_CLASS_SRC_BASE_DIRS
439    */
440   public static final String BASE_DIR_BASE_DIR = "base_dir_base_dir";
441   /**
442      <p>Name of the sub-directory in which the offline versions of external library {@code "package-list"} files are stored--Equal to {@code "offline_package_lists"}.</p>
443
444      <p>This is located in the Codelet {@linkplain CodeletBootstrap#getCodeletConfigDir() configuration directory}.</p>
445
446    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
447    * @see  CodeletBootstrap#EXTERNAL_DOC_ROOT_URL_FILE
448    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
449    */
450   public static final String OFFLINE_PACKAGE_LIST_DIR_NAME = "offline_package_lists";
451   /**
452      <p>How many attempts should be made to retrieve each online package-list? If zero, offline only--Name is {@code "pkglist_online_attempts_per_url"}.</p>
453
454      <p>Must be an integer zero or greater. If not provided (equal to the empty-string: {@code ""}), this defaults to {@link #DEFAULT_ONLINE_PKGLST_ATTEMPTS}.</p>
455
456    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
457    * @see  #getAllJavaDocRoots()
458    * @see  #getOnlinePackageListAttemptCount()
459    */
460   public static final String PKGLIST_ONLINE_ATTEMPT_COUNT = "pkglist_online_attempts_per_url";
461   /**
462      <p>How many milliseconds between each failed attempt?--Name is {@code "pkglist_online_attempt_sleep_mills"}.</p>
463
464      <p>Must be an integer zero or greater. If not provided (equal to the empty-string: {@code ""}), thi defaults to {@link #DEFAULT_ONLINE_PKGLST_SLEEP_MILLS}.</p>
465
466    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
467    * @see  #getOnlinePackageListAttemptSleepMills()
468    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
469    */
470   public static final String PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS = "pkglist_online_attempt_sleep_mills";
471   /**
472      <p>If all online-retrieval attempts fail, should only a warning be logged, or should Codelet stop execution? (Offline package-lists are always retrieved)--Name is {@code "pkglist_if_online_retrieval_fails__warn_crash"}.</p>
473
474    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
475    * @see  #doCrashIfOnlinePackageListFailure()
476    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
477    */
478   public static final String PKGLIST_ONLINE_FAILS_BEHAVIOR = "pkglist_if_online_retrieval_fails__warn_crash";
479   /**
480      <p>When online package-lists are retrieved, should offline package lists be refreshed (or created)?--Name is {@code "pkglist_auto_refresh_offline__yes_no"}.</p>
481
482    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
483    * @see  #doAutoUpdateOfflinePackageLists()
484    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
485    */
486   public static final String AUTO_UPDATE_OFFLINE_PACKAGE_LISTS = "pkglist_auto_refresh_offline__yes_no";
487   /**
488      <p>Filename postfix, plus optional dot-extension that follows each offline name.--Name is {@code "pkglist_offline_name_postfix"}.</p>
489
490    * @see  <code><a href="#tmpl_javadoc"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
491    * @see  #getOfflinePackageListPostfix()
492    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
493    */
494   public static final String PKGLIST_OFFLINE_NAME_POSTFIX = "pkglist_offline_name_postfix";
495   /**
496      <p>Amount that information that should be logged in every taglet-call--Name is {@code "global_debugging__off_12345"}.</p>
497
498      <p>This {@linkplain com.github.xbn.io.DebugLevel#getFromStringOff12345(String, String) must be equal to}<ul>
499         <li>{@code "off"}: No automated debugging.</li>
500         <li>A digit between one and five: An arbitrary number representing the amount of debugging information that will be output.</li>
501      </ul></p>
502
503      <p>This is the {@linkplain #getGlobalDebugLevel() global debugging level} used by all taglets. An individual taglet may override this by prepending "{@link CodeletInstance#DEBUG_LEVEL_PREFIX_PREFIX [DEBUG_LEVEL_#]}" to its text. If the {@linkplain CodeletInstance#getDebugLevel() taglet's level} is lower than or equal to the global level, it is ignored.</p>
504
505      <p>For very specific control over what is output <i>without having to recompile code</i>, create a &quot;{@link CodeletBootstrap#NAMED_DEBUGGERS_CONFIG_FILE named debugger}&quot;, each of which has a  level-number associated to it. If the actual (global or taglet) debugging level is equal-to-or-higher, it's information is output.</p>
506
507      <h4>What is logged</h4>
508
509      <p>The examples in this section assumes that {@code CodeletBaseConfig} is <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html">statically imported</a> &quot;en masse&quot;:
510      <br/> &nbsp; &nbsp; <code>import  static com.github.aliteralmind.codelet.CodeletBaseConfig.*;</code></p>
511
512      <p>To output something even if the debugging level is {@code "off"}:</p>
513
514<blockquote><code>{@link #debugln(Object) debugln}(&quot;Important information&quot;);</code></blockquote>
515
516      <p> To output only when global debugging is on (level one or greater):</p>
517
518<blockquote><code>if({@link #isDebugOn(CodeletInstance) isDebugOn}(null))  {
519   debugln(&quot;Important information&quot;)
520}</code></blockquote>
521
522      <p>To output when global debugging is at least level three:</p>
523
524<blockquote><code>if({@link #isDebugOn(int, CodeletInstance) isDebugOn}(3, null))  {
525   debugln(&quot;Important information&quot;)
526}</code></blockquote>
527
528      <p>To output when global or taglet debugging is at least three:</p>
529
530<blockquote><code>if({@link #isDebugOn(int, CodeletInstance) isDebugOn}(3, <i>[the-taglet-instance]</i>))  {
531   debugln(&quot;Important information&quot;)
532}</code></blockquote>
533
534    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
535    * @see  #DEBUG_DESTINATION
536    * @see  #getGlobalDebugLevel()
537    * @see  <a href="{@docRoot}/overview-summary.html#xmpl_links_debug">Overview JavaDoc link example</a>
538    */
539   public static final String GLOBAL_DEBUG_LEVEL = "global_debugging__off_12345";
540   /**
541      <p>When debugging is on, where should output be written to?--Name is {@code "debug_to__console_path"}.</p>
542
543      <p>This must be one of two values:<ul>
544         <li>{@code "console"}: Sets {@link #getDebugAptr() getDebugAptr}{@code ()} to <code>{@link com.github.xbn.io.TextAppenter TextAppenter}.{@link com.github.xbn.io.TextAppenter#CONSOLE CONSOLE}</code></li>
545         <li>The path to a writable file: Sets {@code getDebugAptr()} to
546         <br/> &nbsp; &nbsp; <code>{@link com.github.xbn.io.NewTextAppenterFor NewTextAppenterFor}.{@link com.github.xbn.io.NewTextAppenterFor#file(String, AppendOrOverwrite) file}(dbgAptrStr, {@link com.github.xbn.io.AppendOrOverwrite AppendOrOverwrite}.{@link com.github.xbn.io.AppendOrOverwrite#APPEND APPEND})</code></li>
547      </ul>In order to allow debugging at any time, even when the {@linkplain #GLOBAL_DEBUG_LEVEL debugging level} is set to off, this value is required.</p>
548
549    * @see  <code><a href="#debugging"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
550    * @see  #getDebugAptr()
551    */
552   public static final String DEBUG_DESTINATION = "debug_to__console_path";
553   /**
554      <p>Prepended to all {@code "default_*_template_path"} values--Name is {@code "default_template_directory_prefix"}.</p>
555
556      <p>This value may be the empty string ({@code ""}), and may include the &quot;{@link #BASE_DIR_BASE_DIR base_dir_base_dir}&quot;</p>
557
558      <p>All default template paths are required, must exist and be readable, and must refer to a valid Codelet template of its type. They may be in any of the following locations, which are searched for in order:<ol>
559         <li>A file name, which exists in the same directory as this configuration file.</li>
560         <li>A relative path, which exists off of the directory from which the Java Virtual Machine was invoked.</li>
561         <li>An absolute path.</li>
562      </ol>
563
564      <p>View the locally installed templates:<ul>
565         <li><a href="{@docRoot}/../codelet_config/default_templates/source_code.txt">{@code {@.codelet}}</a></li>
566         <li><a href="{@docRoot}/../codelet_config/default_templates/console_out.txt">{@code {@.codelet.out}}</a></li>
567         <li><a href="{@docRoot}/../codelet_config/default_templates/src_and_out.txt">{@code {@.codelet.and.out}}</a></li>
568         <li><a href="{@docRoot}/../codelet_config/default_templates/file_text.txt">{@code {@.file.textlet}}</a></li>
569      </ul>These links assume the default template directory is &quot;{@code {@docRoot}/../codelet_config/default_templates/}&quot;</p>
570
571    * @see  <code><a href="#tmpl_defaults"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
572    * @see  #DEFAULT_SRC_CODE_TMPL_PATH
573    * @see  #DEFAULT_DOT_OUT_TMPL_PATH
574    * @see  #DEFAULT_FILE_TEXT_TMPL_PATH
575    * @see  #DEFAULT_AND_OUT_TMPL_PATH
576    * @see  #USER_EXTRA_GAPS_CLASS_NAME
577    * @see  #USER_TEMPLATE_BASE_DIR
578    */
579   public static final String DEFAULT_TPML_DIR_PREFIX = "default_template_directory_prefix";
580   /**
581      <p>Path to the default {@linkplain type.SourceCodeTemplate template} used for (source-code) {@link CodeletType#SOURCE_CODE {@.codelet}} taglets--Name is {@code "default_source_codelet_template_path"}.</p>
582
583    * @see  <code><a href="#tmpl_defaults"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
584    * @see  #DEFAULT_TPML_DIR_PREFIX
585    * @see  #getDefaultSourceCodeTemplatePath()
586    */
587   public static final String DEFAULT_SRC_CODE_TMPL_PATH = "default_source_codelet_template_path";
588   /**
589      <p>Path to the default {@linkplain type.ConsoleOutTemplate template} used for {@link CodeletType#CONSOLE_OUT {@.codelet.out}} taglets--Name is {@code "default_dot_out_template_path"}.</p>
590
591    * @see  <code><a href="#tmpl_defaults"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
592    * @see  #DEFAULT_TPML_DIR_PREFIX
593    * @see  #getDefaultConsoleOutTemplatePath()
594    */
595   public static final String DEFAULT_DOT_OUT_TMPL_PATH = "default_dot_out_template_path";
596   /**
597      <p>Path to the default {@linkplain type.SourceAndOutTemplate template} used for {@link CodeletType#SOURCE_AND_OUT {@.codelet.and.out}} taglets--Name is {@code "default_and_out_template_path"}.</p>
598
599    * @see  <code><a href="#tmpl_defaults"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
600    * @see  #DEFAULT_TPML_DIR_PREFIX
601    * @see  #getDefaultSourceAndOutTemplatePath()
602    */
603   public static final String DEFAULT_AND_OUT_TMPL_PATH = "default_and_out_template_path";
604   /**
605      <p>Path to the default {@linkplain type.FileTextTemplate template} used for {@link CodeletType#FILE_TEXT {@.file.textlet}} taglets--Name is {@code "default_file_textlet_template_path"}.</p>
606
607    * @see  <code><a href="#tmpl_defaults"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
608    * @see  #DEFAULT_TPML_DIR_PREFIX
609    * @see  #getDefaultFileTextTemplatePath()
610    */
611   public static final String DEFAULT_FILE_TEXT_TMPL_PATH = "default_file_textlet_template_path";
612   /**
613      <p>Fully-qualified name of the class that defines {@linkplain CustomizationInstructions#orderedAlterers(Appendable, NullElement, ExpirableElements, MultiAlterType, TextLineAlterer...) alterers} used by all {@linkplain BasicCustomizers pre-built customizers}, and are accessible in <a href="CustomizationInstructions.html#overview">custom customizers</a>--Name is {@code "default_alterers_class_name"}.</p>
614
615      <p>When provided, the class it represents must {@linkplain java.lang.Class#forName(String) exist}, implement {@link com.github.aliteralmind.codelet.alter.DefaultAlterGetter}, and have a no-parameter constructor. When not provided (equal to the empty-string {@code ""}), {@link DefaultDefaultAlterGetter} is used.</p>
616
617    * @see  <code><a href="#base_dirs_other"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></a></code>
618    * @see  #getDefaultAlterGetter()
619    */
620   public static final String DEFAULT_ALTERERS_CLASS_NAME = "default_alterers_class_name";
621
622   /**
623      <p>Character placed immediately before gap names--Name is {@code "gap_name_prefix_char"}.</p>
624
625      <p>If not provided, defaults to <code>{@link com.github.aliteralmind.templatefeather.GapCharConfig GapCharConfig}.{@link com.github.aliteralmind.templatefeather.GapCharConfig#DEFAULT_PREFIX_CHAR DEFAULT_PREFIX_CHAR}</code></p>
626
627    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
628    * @see  #GAP_NAME_POSTFIX_CHAR
629    * @see  #GAP_NAME_LITERAL_PREFIX
630    * @see  #getGapCharConfig()
631    */
632   public static final String GAP_NAME_PREFIX_CHAR = "gap_name_prefix_char";
633   /**
634      <p>Character placed immediately after gap names--Name is {@code "gap_name_postfix_char"}.</p>
635
636      <p>If not provided, defaults to <code>{@link com.github.aliteralmind.templatefeather.GapCharConfig GapCharConfig}.{@link com.github.aliteralmind.templatefeather.GapCharConfig#DEFAULT_POSTFIX_CHAR DEFAULT_PREFIX_CHAR}</code></p>
637
638    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
639    * @see  #GAP_NAME_PREFIX_CHAR
640    * @see  #GAP_NAME_LITERAL_POSTFIX
641    * @see  #getGapCharConfig()
642    */
643   public static final String GAP_NAME_POSTFIX_CHAR = "gap_name_postfix_char";
644   /**
645      <p>Literal representation of the prefix char, for use in between texts--Name is {@code "gap_literal_prefix_char"}.</p>
646
647      <p>If not provided, defaults to <code>{@link com.github.aliteralmind.templatefeather.GapCharConfig GapCharConfig}.{@link com.github.aliteralmind.templatefeather.GapCharConfig#DEFAULT_LITERAL_PREFIX DEFAULT_LITERAL_PREFIX}</code></p>
648
649    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
650    * @see  #GAP_NAME_PREFIX_CHAR
651    * @see  #GAP_NAME_LITERAL_POSTFIX
652    * @see  #getGapCharConfig()
653    */
654   public static final String GAP_NAME_LITERAL_PREFIX = "gap_literal_prefix_char";
655   /**
656      <p>Literal representation of the postfix char, for use in between texts--Name is {@code "gap_literal_name_postfix_char"}.</p>
657
658      <p>If not provided, defaults to <code>{@link com.github.aliteralmind.templatefeather.GapCharConfig GapCharConfig}.{@link com.github.aliteralmind.templatefeather.GapCharConfig#DEFAULT_LITERAL_PREFIX DEFAULT_LITERAL_PREFIX}</code></p>
659
660    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
661    * @see  #GAP_NAME_POSTFIX_CHAR
662    * @see  #GAP_NAME_LITERAL_PREFIX
663    * @see  #getGapCharConfig()
664    */
665   public static final String GAP_NAME_LITERAL_POSTFIX = "gap_literal_name_postfix_char";
666   /**
667      <p>Fully-qualified name of the class that defines extra gaps that can be placed in Codelet templates--Name is {@code "user_extra_gaps_class"}.</p>
668
669      <p>If there are no extra gaps, set this to the empty-string. Otherwise, the class it represents must {@linkplain java.lang.Class#forName(String) exist}, implement {@link UserExtraGapGetter}, and have a no-parameter constructor.</p>
670
671    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
672    * @see  #DEFAULT_TPML_DIR_PREFIX
673    * @see  #getUserExtraGapsClassName()
674    */
675   public static final String USER_EXTRA_GAPS_CLASS_NAME = "user_extra_gaps_class";
676   /**
677      <p>Directory in which any custom (user-created) templates are stored--Name is {@code "user_template_base_dir"}.</p>
678
679      <p>This is optional and not validated in any way. Its value may include the &quot;{@link #BASE_DIR_BASE_DIR base_dir_base_dir}&quot;.</p>
680
681    * @see  <code><a href="#tmpl_gaps"><IMG SRC="{@docRoot}/resources/up_arrow.gif"/></a></code>
682    * @see  #getCustomTemplateDir()
683    */
684   public static final String USER_TEMPLATE_BASE_DIR = "user_template_base_dir";
685   /**
686      <p>Load configuration and get the instance. Call only once.</p>
687
688    * @param  props  May not be {@code null}, and must be a valid {@linkplain CodeletBaseConfig Codelet properties} file.
689    * @return  #INSTANCE
690    * @exception  IllegalStateException  If configuration was already loaded.
691    * @see  com.github.xbn.util.PropertiesUtil
692    */
693   static final CodeletBaseConfig loadConfigGetInstance(Properties props, String config_baseDir, Iterator<String> externalJDDocRoot_configLineItr, Iterator<String> rqdDbgLevels_configLineItr, Iterator<String> debugLevels_configLineItr) throws NoSuchFileException, AccessDeniedException, MalformedURLException, IOException, InterruptedException  {
694      if(wasLoaded())  {
695         throw  new IllegalStateException("wasLoaded() is true.");
696      }
697      String dbgLvlStr = null;
698      try  {
699         dbgLvlStr = props.getProperty(GLOBAL_DEBUG_LEVEL, "");
700      }  catch(RuntimeException rx)  {
701         throw  CrashIfObject.nullOrReturnCause(props, "props", null, rx);
702      }
703
704      dbgLevel = DebugLevel.getFromStringOff12345(dbgLvlStr, GLOBAL_DEBUG_LEVEL);
705
706      String dbgAptrStr = props.getProperty(DEBUG_DESTINATION, "");
707      if(dbgAptrStr.equals("console"))  {
708         dbgAptr =  TextAppenter.CONSOLE;
709         doDebugToConsole = true;
710      }  else  {
711         dbgAptr = NewTextAppenterFor.file(dbgAptrStr, AppendOrOverwrite.APPEND);
712         doDebugToConsole = false;
713      }
714
715      if(dbgLevel.isOn())  {
716         debugln("Loading Codelet configuration");
717         debugln("   Loading base config");
718         debugln("      Loading debug level config file...");
719      }
720
721      //Named debuggers cannet be used until the named-level map is created!
722
723      int namedDebugLevelsRqd = 0;
724      Map<String,DebugLevel> rqdDbgLevelNameMap = NamedDebuggers.
725         newMapFromConfigFile(null, rqdDbgLevels_configLineItr,
726         "rqdDbgLevels_configLineItr",
727         null);    //debug
728      namedDebugLevelsRqd = rqdDbgLevelNameMap.size();
729
730      namedDebugLevels = new NamedDebuggers(rqdDbgLevelNameMap,
731         debugLevels_configLineItr,
732         "rqdDbgLevelNameMap",
733         null);    //debug
734
735      //NOW named debuggers can be used.
736
737      if(isDebugOn(null, "zzconfiguration.nameddebuglevels.listallafterload"))  {
738         debugln("All named debuggers:" + MapUtil.toString(namedDebugLevels.getMap(), null));
739      }
740
741      namedDebugLevels.setAllQueriesDebug(
742         getDebugApblIfOn(null, "zzconfiguration.nameddebuglevels.eachquery"));
743
744      String baseDirBaseRplcmntQuoted = Matcher.quoteReplacement(props.getProperty(BASE_DIR_BASE_DIR, ""));
745
746      xmplSrcBaseDir = get1stDollarBASERplcd(
747         props.getProperty(EXAMPLE_CLASS_SRC_BASE_DIR, ""),
748         baseDirBaseRplcmntQuoted);
749      String enclosingBaseDirPropVal = props.getProperty(ENCLOSING_CLASS_SRC_BASE_DIRS, "");
750      enclosingBaseDirs = null;
751      if(enclosingBaseDirPropVal.length() == 0)  {
752         throw  new IllegalArgumentException("No values for " + ENCLOSING_CLASS_SRC_BASE_DIRS + ". At least one required.");
753      }  else  {
754         enclosingBaseDirs = enclosingBaseDirPropVal.split(",");
755         for(int i = 0; i < enclosingBaseDirs.length; i++)  {
756            enclosingBaseDirs[i] = get1stDollarBASERplcd(
757               enclosingBaseDirs[i], baseDirBaseRplcmntQuoted);
758            new PathMustBe().existing().readable().
759               getOrCrashIfBad(enclosingBaseDirs[i],
760               "Element " + i + " in " + ENCLOSING_CLASS_SRC_BASE_DIRS);
761         }
762      }
763      enclosingBaseDirList = Collections.unmodifiableList(Arrays.asList(enclosingBaseDirs));
764
765      char gapNamePreChar = PropertiesUtil.getWithEmptyDefault(props, GAP_NAME_PREFIX_CHAR, Empty.OK, GapCharConfig.DEFAULT_PREFIX_CHAR);
766      char gapNamePostChar = PropertiesUtil.getWithEmptyDefault(props, GAP_NAME_POSTFIX_CHAR, Empty.OK, GapCharConfig.DEFAULT_POSTFIX_CHAR);
767      String gapLiteralPre = props.getProperty(GAP_NAME_LITERAL_PREFIX, GapCharConfig.DEFAULT_LITERAL_PREFIX);
768      String gapLiteralPost = props.getProperty(GAP_NAME_LITERAL_POSTFIX, GapCharConfig.DEFAULT_LITERAL_POSTFIX);
769
770      gapCharConfig = new GapCharConfig(gapNamePreChar, gapNamePostChar, gapLiteralPre, gapLiteralPost);
771
772                String defaultAlterGetterClsNm = props.getProperty(DEFAULT_ALTERERS_CLASS_NAME, "");
773      if(defaultAlterGetterClsNm.length() == 0)  {
774         defaultAlterGetter = new DefaultDefaultAlterGetter();
775         if(isDebugOn(null, "zzconfiguration.progress"))  {
776            debugln("      No default-alter-getter class name provided. Using DefaultDefaultAlterGetter");
777         }
778      }  else  {
779         defaultAlterGetter = ReflectRtxUtil.<DefaultAlterGetter>getNewInstanceFromNoParamCnstr(
780            defaultAlterGetterClsNm, DefaultAlterGetter.class,
781            getDebugApblIfOn(null, "zzconfiguration.progress"));
782      }
783
784      String tmplBaseDir = props.getProperty(DEFAULT_TPML_DIR_PREFIX, "");
785      defaultSrcTmplPath = get1stDollarBASERplcd(
786         tmplBaseDir + props.getProperty(DEFAULT_SRC_CODE_TMPL_PATH, ""),
787         baseDirBaseRplcmntQuoted);
788      defaultOutTmplPath = get1stDollarBASERplcd(
789         tmplBaseDir + props.getProperty(DEFAULT_DOT_OUT_TMPL_PATH, ""),
790         baseDirBaseRplcmntQuoted);
791      defaultSrcAndOutTmplPath = get1stDollarBASERplcd(
792         tmplBaseDir + props.getProperty(DEFAULT_AND_OUT_TMPL_PATH, ""),
793         baseDirBaseRplcmntQuoted);
794      defaultFileTextTmplPath = get1stDollarBASERplcd(
795         tmplBaseDir + props.getProperty(DEFAULT_FILE_TEXT_TMPL_PATH, ""),
796         baseDirBaseRplcmntQuoted);
797
798      userExtraGapsClassNm = props.getProperty(USER_EXTRA_GAPS_CLASS_NAME, "");
799
800      customTmplDir = get1stDollarBASERplcd(
801         props.getProperty(USER_TEMPLATE_BASE_DIR, ""),
802         baseDirBaseRplcmntQuoted);
803
804      blackWhiteList = FilenameBlackWhiteList.newFromProperties(props, ",", BLACK_WHITE_LIST_TYPE,
805         BLACK_WHITE_LIST_CASE, BLACK_WHITE_PROPER_LIST, BLACK_WHITE_OVERRIDE_LIST,
806         getDebugApblIfOn(null, "zzconfiguration.blackwhitelist.loading"),
807         getDebugApblIfOn(null, "zzconfiguration.blackwhitelist.usage"));
808
809      jdTgtClsMapInitCapacity = PropertiesUtil.getWithEmptyDefault(props,
810         UNIQUE_JD_CLASS_TARGET_INIT_CAPACITY, Empty.OK,
811         DEFAULT_JD_TARGET_CLASS_MAP_INIT_CAPACITY);
812
813      doCrashIfAlterNotMade = PropertiesUtil.getWithEmptyDefault(props,
814         ALTERATION_NOT_MADE_CRASH, "yes", "no", Empty.BAD, false);
815
816      onlinePkgLstAttemptCount = PropertiesUtil.getWithEmptyDefault(props,
817         PKGLIST_ONLINE_ATTEMPT_COUNT, Empty.OK, DEFAULT_ONLINE_PKGLST_ATTEMPTS);
818      onlinePkgLstAttemptSleepMills = PropertiesUtil.getWithEmptyDefault(props,
819         PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS, Empty.OK,
820         DEFAULT_ONLINE_PKGLST_SLEEP_MILLS);
821      doCrashIfOnlinePkgLstFails = PropertiesUtil.getWithEmptyDefault(props,
822         PKGLIST_ONLINE_FAILS_BEHAVIOR, "crash", "warn", Empty.BAD, false);
823      doAutoUpdateOfflinePkgLsts = PropertiesUtil.getWithEmptyDefault(props,
824         AUTO_UPDATE_OFFLINE_PACKAGE_LISTS, "yes", "no", Empty.BAD, false);
825      offlinePkgLstNamePost = props.getProperty(PKGLIST_OFFLINE_NAME_POSTFIX, "");
826
827      allDocRoots = AllOnlineOfflineDocRoots.newFromConfigLineIterator(
828         externalJDDocRoot_configLineItr,
829         config_baseDir + OFFLINE_PACKAGE_LIST_DIR_NAME + FILE_SEP,
830            offlinePkgLstNamePost,
831         onlinePkgLstAttemptCount, onlinePkgLstAttemptSleepMills,
832         RefreshOffline.getForBoolean(doAutoUpdateOfflinePkgLsts),
833         IfError.getCRASHIfTrue(doCrashIfOnlinePkgLstFails),
834         getDebugApblIfOn(null, "zzconfiguration.progress"),
835         getDebugAptr().getAppendable());  //Required!!
836
837      if(isDebugOn(null, "zzconfiguration.allvaluessummary"))  {
838         debugln("   Codelet base-configuration loaded:");
839         debugln("      - " + EXAMPLE_CLASS_SRC_BASE_DIR + ": \"" + xmplSrcBaseDir + "\"");
840         debugln("      - " + ENCLOSING_CLASS_SRC_BASE_DIRS + ": \"" + Arrays.toString(enclosingBaseDirList.toArray()) + "\"");
841         debugln("      - " + DEFAULT_ALTERERS_CLASS_NAME + ": " +
842            ((defaultAlterGetter == null) ? null : defaultAlterGetter.getClass().getName()));
843         debugln("      Templates:");
844         debugln("        - Gap-name character configuration: " + gapCharConfig);
845         debugln("        - " + USER_EXTRA_GAPS_CLASS_NAME + ": \"" + userExtraGapsClassNm + "\"");
846         debugln("        - " + DEFAULT_TPML_DIR_PREFIX + ": \"" + tmplBaseDir + "\"");
847         debugln("        - " + DEFAULT_SRC_CODE_TMPL_PATH + ": \"" + defaultSrcTmplPath + "\"");
848         debugln("        - " + DEFAULT_DOT_OUT_TMPL_PATH + ": \"" + defaultOutTmplPath + "\"");
849         debugln("        - " + DEFAULT_AND_OUT_TMPL_PATH + ": \"" + defaultSrcAndOutTmplPath + "\"");
850         debugln("        - " + DEFAULT_FILE_TEXT_TMPL_PATH + ": \"" + defaultFileTextTmplPath + "\"");
851         debugln("        - " + USER_TEMPLATE_BASE_DIR + ": \"" + customTmplDir + "\"");
852         debugln("      JavaDoc:");
853         debugln("        - " + UNIQUE_JD_CLASS_TARGET_INIT_CAPACITY + ": " + jdTgtClsMapInitCapacity);
854         debugln("        - " + PKGLIST_ONLINE_ATTEMPT_COUNT + ": " + onlinePkgLstAttemptCount);
855         debugln("        - " + PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS + ": " + onlinePkgLstAttemptSleepMills);
856         debugln("        - doCrashIfOnlinePackageListFailure(): " + doCrashIfOnlinePkgLstFails);
857         debugln("        - doAutoUpdateOfflinePackageLists(): " + doAutoUpdateOfflinePkgLsts);
858         debugln("        - doAutoUpdateOfflinePackageLists(): " + doAutoUpdateOfflinePkgLsts);
859         debugln("        - doCrashIfAlterNotMade(): " + doCrashIfAlterNotMade);
860         debugln("        - " + PKGLIST_OFFLINE_NAME_POSTFIX + ": \"" + offlinePkgLstNamePost + "\"");
861         debugln("        - getAllJavaDocRoots(): " + allDocRoots);
862         debugln("      Debugging:");
863         debugln("        - " + GLOBAL_DEBUG_LEVEL + ": " + dbgLevel);
864         debugln("        - " + DEBUG_DESTINATION + ": " + dbgAptr);
865         debugln("        - Black/white list: " + blackWhiteList);
866         debugln("        - Named debuggers: " + namedDebugLevels.getMap().size() + " (" + namedDebugLevelsRqd + " required)");
867         debugln("   (done--ready to load CodeletTemplateConfig)");
868      }
869
870      wasLoaded = true;
871
872      return  INSTANCE;
873   }
874      private static final String get1stDollarBASERplcd(String maybe_containsDollarBASE, String baseDirBase_rplcmntQuoted)  {
875         return  dollarSignBASEMtchr.reset(maybe_containsDollarBASE).
876            replaceFirst(baseDirBase_rplcmntQuoted);
877      }
878      private static final Matcher dollarSignBASEMtchr = Pattern.compile("${BASE}", Pattern.LITERAL).matcher("");
879
880   /**
881      <p>Was configuration loaded?.</p>
882
883    * @return  {@code true} If all values loaded successfully.
884    */
885   public static final boolean wasLoaded()  {
886      return  wasLoaded;
887   }
888   /**
889      <p>Path to the default template used for (source-code) {@code {@.codelet}} taglets.</p>
890
891    * @see  #DEFAULT_SRC_CODE_TMPL_PATH
892    */
893   public static final String getDefaultSourceCodeTemplatePath()  {
894      return  defaultSrcTmplPath;
895   }
896   /**
897      <p>Path to the default template used for {@code {@.codelet.out}} taglets.</p>
898
899    * @see  #DEFAULT_DOT_OUT_TMPL_PATH
900    */
901   public static final String getDefaultConsoleOutTemplatePath()  {
902      return  defaultOutTmplPath;
903   }
904   /**
905      <p>Path to the default template used for {@code {@.codelet.and.out}} taglets.</p>
906
907    * @see  #DEFAULT_AND_OUT_TMPL_PATH
908    */
909   public static final String getDefaultSourceAndOutTemplatePath()  {
910      return  defaultSrcAndOutTmplPath;
911   }
912   /**
913      <p>Path to the default template used for {@code {@.file.textlet}} taglets.</p>
914
915    * @see  #DEFAULT_FILE_TEXT_TMPL_PATH
916    */
917   public static final String getDefaultFileTextTemplatePath()  {
918      return  defaultFileTextTmplPath;
919   }
920   /**
921      <p>Write a message to the console and, if debugging is both on and <i>not</i> to the console, writes it via the debug outputter as well.</p>
922
923      <p>This<ol>
924         <li>Calls <code>System.out.println(message);</code></li>
925         <li>If debugging is both {@linkplain #isDebugOn(CodeletInstance) on} and <i>not</i> {@linkplain #doDebugToConsole() to the console}, this also calls
926         <br/> &nbsp; &nbsp; {@link #debugln(Object) debugln}{@code (message)}</li>
927      </ol></p>
928
929    * @param  message  <i>Should</i> not be {@code null} or empty.
930    * @see  #debugAndToConsole(CodeletInstance, Object)
931    */
932   public static final void debuglnAndToConsole(CodeletInstance instance, Object message)  {
933      System.out.println(message);
934      if(isDebugOn(instance)  &&  !doDebugToConsole())  {
935         debugln(message);
936      }
937   }
938   /**
939      <p>Write a message to the console and, if debugging is both on and <i>not</i> to the console, writes it via the debug outputter as well.</p>
940
941      <p>This<ol>
942         <li>Calls <code>System.out.print(message);</code></li>
943         <li>If debugging is both {@linkplain #isDebugOn(CodeletInstance) on} and <i>not</i> {@linkplain #doDebugToConsole() to the console}, this also calls
944         <br/> &nbsp; &nbsp; {@link #debug(Object) debug}{@code (message)}</li>
945      </ol></p>
946
947    * @param  message  <i>Should</i> not be {@code null} or empty.
948    * @see  #debuglnAndToConsole(CodeletInstance, Object)
949    */
950   public static final void debugAndToConsole(CodeletInstance instance, Object message)  {
951      System.out.print(message);
952      if(isDebugOn(instance)  &&  !doDebugToConsole())  {
953         debug(message);
954      }
955   }
956   /**
957      <p>Write a message to the debugging output.</p>
958
959    * <p>Equal to
960      <br/> &nbsp; &nbsp; <code>{@link #getDebugAptr() getDebugAptr}().{@link com.github.xbn.io.TextAppenter#appent(Object) appent}(message)</code></p>
961
962    * @see  #debugln(Object)
963    */
964   public static final void debug(Object message)  {
965      getDebugAptr().appent(message);
966   }
967   /**
968      <p>Write a message to the debugging output.</p>
969
970    * <p>Equal to
971      <br/> &nbsp; &nbsp; <code>{@link #getDebugAptr() getDebugAptr}().{@link com.github.xbn.io.TextAppenter#appentln(Object) appentln}(message)</code></p>
972
973    * @see  #debug(Object)
974    */
975   public static final void debugln(Object message)  {
976      getDebugAptr().appentln(message);
977   }
978   /**
979      <p>Is debugging output being written to the console?. This is used only to avoid {@linkplain #debuglnAndToConsole(CodeletInstance, Object) duplicate messages} when {@linkplain #isDebugOn(CodeletInstance) debugging is on}.</p>
980
981    * @see  #getGlobalDebugLevel()
982    */
983   public static final boolean doDebugToConsole()  {
984      return  doDebugToConsole;
985   }
986   /**
987      <p>The amount of debugging, beyond ......logging......, that is written in every taglet call.</p>
988
989    * @see  #GLOBAL_DEBUG_LEVEL
990    * @see  #isDebugOn(CodeletInstance) isDebugOn(ci)
991    * @see  #isDebugOn(CodeletInstance, String) isDebugOn(ci,s)
992    * @see  #getDebugAptr()
993    * @see  #doDebugToConsole()
994    * @see  #debuglnAndToConsole(CodeletInstance, Object) log
995    */
996   public static final DebugLevel getGlobalDebugLevel()  {
997      return  dbgLevel;
998   }
999   /**
1000      <p>Is debugging on, either globally or for a single taglet?.</p>
1001
1002    * @param  instance  May be {@code null}.
1003    * @return  <code>{@link #getGlobalDebugLevel() getGlobalDebugLevel}().{@link com.github.xbn.io.DebugLevel#isThisOrAnyOn(DebugLevel...) isThisOrAnyOn}(instance.{@link CodeletInstance#getDebugLevel() getDebugLevel}())</code>
1004    * @see  #isDebugOn(CodeletInstance, String)
1005    * @see  #isDebugOn(int, CodeletInstance)
1006    */
1007   public static final boolean isDebugOn(CodeletInstance instance)  {
1008      return  getGlobalDebugLevel().isThisOrAnyOn(getInstanceDbgLevelOrNull(instance));
1009   }
1010      private static final DebugLevel getInstanceDbgLevelOrNull(CodeletInstance instance)  {
1011         return  ((instance == null) ? null
1012            :  instance.getDebugLevel());
1013      }
1014   /**
1015      <p>Is debugging on and at least a certain level?.</p>
1016
1017    * @param  instance  May be {@code null}.
1018    * @return  <code>{@link #getGlobalDebugLevel() getGlobalDebugLevel}().{@link com.github.xbn.io.DebugLevel#isHighestOnAndAtLeast(int, DebugLevel...) isHighestOnAndAtLeast}(min_level, instance.{@link CodeletInstance#getDebugLevel() getGlobalDebugLevel}())</code>
1019    * @see  #isDebugOn(CodeletInstance)
1020    */
1021   public static final boolean isDebugOn(int min_level, CodeletInstance instance)  {
1022//System.out.println("isDebugOn: global=" + getGlobalDebugLevel() + ", instance=" + getInstanceDbgLevelOrNull(instance) + ", highest-at-least-" + min_level + "=" + getGlobalDebugLevel().isHighestOnAndAtLeast(min_level, getInstanceDbgLevelOrNull(instance)) + "");
1023      return  getGlobalDebugLevel().isHighestOnAndAtLeast(min_level, getInstanceDbgLevelOrNull(instance));
1024   }
1025   /**
1026      <p>Is debugging on and at most a certain level?.</p>
1027
1028    * @param  instance  May be {@code null}.
1029    * @return  <code>({@link #getGlobalDebugLevel() getGlobalDebugLevel}().{@link com.github.xbn.io.DebugLevel#getHighestNumber(DebugLevel...) getHighestNumber}(instance.{@link CodeletInstance#getDebugLevel() getGlobalDebugLevel}()) &lt;= max_level)</code>
1030    */
1031   public static final boolean isDebugLevelAtMost(int max_level, CodeletInstance instance)  {
1032//System.out.println("isDebugLevelAtMost: global=" + getGlobalDebugLevel() + ", instance=" + getInstanceDbgLevelOrNull(instance) + ", highest=" + getGlobalDebugLevel().getHighestNumber(getInstanceDbgLevelOrNull(instance)) + ", max_level=" + max_level + ", returning=" + (getGlobalDebugLevel().getHighestNumber(getInstanceDbgLevelOrNull(instance)) <= max_level) + "");
1033      return  (getGlobalDebugLevel().getHighestNumber(getInstanceDbgLevelOrNull(instance)) <= max_level);
1034   }
1035   /**
1036      <p>The debugging outputter.</p>
1037
1038    * @see  #DEBUG_DESTINATION
1039    * @see  #getGlobalDebugLevel()
1040    * @see  #getDebugApblIfOn(CodeletInstance) getDebugApblIfOn
1041    * @see  #getDebugApblIfOn(int, CodeletInstance) getDebugApblIfOn
1042    * @see  #doDebugToConsole()
1043    */
1044   public static final TextAppenter getDebugAptr()  {
1045      return  dbgAptr;
1046   }
1047   /**
1048      <p>If debugging is on, get an appendable.</p>
1049
1050    * @return  <code>{@link #getDebugApblIfOn(int, CodeletInstance) getDebugApblIfOn}(0, instance)</code>
1051    */
1052   public static final Appendable getDebugApblIfOn(CodeletInstance instance)  {
1053      return  getDebugApblIfOn(0, instance);
1054   }
1055   /**
1056      <p>If debugging is on, get an appenter.</p>
1057
1058    * @return  <code>{@link #getDebugAptrIfOn(int, CodeletInstance) getDebugAptrIfOn}(0, instance)</code>
1059    */
1060   public static final TextAppenter getDebugAptrIfOn(CodeletInstance instance)  {
1061      return  getDebugAptrIfOn(0, instance);
1062   }
1063   /**
1064      <p>If debugging is on and at least a certain level, get an appendable.</p>
1065
1066    * @return  <code>(!{@link #isDebugOn(int, CodeletInstance) isDebugOn}(min_level, instance) ? null
1067         :  {@link #getDebugAptr() getDebugAptr}().{@link com.github.xbn.io.TextAppenter#getAppendable() getAppendable}()))</code>
1068    * @see  #getDebugApblIfOn(CodeletInstance) getDebugApblIfOn(ci)
1069    * @see  #getDebugAptrIfOn(int, CodeletInstance) getDebugAptrIfOn(i,ci)
1070    */
1071   public static final Appendable getDebugApblIfOn(int min_level, CodeletInstance instance)  {
1072      return  (!isDebugOn(min_level, instance) ? null
1073         :  getDebugAptr().getAppendable());
1074   }
1075   /**
1076      <p>If debugging is on and at least a certain level, get an appenter.</p>
1077
1078    * @return  <code>(!{@link #isDebugOn(int, CodeletInstance) isDebugOn}(min_level, instance) ? null
1079         :  {@link #getDebugAptr() getDebugAptr}().{@link com.github.xbn.io.TextAppenter#getAppendable() getAppendable}()))</code>
1080    * @see  #getDebugAptrIfOn(CodeletInstance) getDebugAptrIfOn(ci)
1081    * @see  #getDebugApblIfOn(int, CodeletInstance) getDebugApblIfOn(i,ci)
1082    */
1083   public static final TextAppenter getDebugAptrIfOn(int min_level, CodeletInstance instance)  {
1084      return  (!isDebugOn(min_level, instance) ? null
1085         :  getDebugAptr());
1086   }
1087   /**
1088      <p>Immutable map containing all named debug levels (both {@linkplain CodeletBootstrap#NAMED_DEBUGGERS_CONFIG_FILE required} and {@linkplain CodeletBootstrap#CODELET_RQD_NAMED_DBGRS_CONFIG_FILE user-created}).</p>
1089
1090    * @see  #isDebugOn(CodeletInstance, String)
1091    * @see  #getDebugApblIfOn(CodeletInstance, String) getDebugApblIfOn(ci,s)
1092    * @see  #getDebugAptrIfOn(CodeletInstance, String) getDebugAptrIfOn(ci,s)
1093    */
1094   public static final NamedDebuggers getNamedDebuggers()  {
1095      return  namedDebugLevels;
1096   }
1097   /**
1098      <p>Is a named debuggers active?.</p>
1099
1100    * @param  instance  May be {@code null}.
1101    * @return  <code>{@link #getNamedDebuggers() getNamedDebuggers}().{@link com.github.aliteralmind.codelet.util.NamedDebuggers#isActive(String, DebugLevel, DebugLevel...) isActive}(name,
1102      <br/> &nbsp; &nbsp; {@link #getGlobalDebugLevel() getGlobalDebugLevel}(), instance.{@link CodeletInstance#getDebugLevel() getDebugLevel}()</code>
1103    * @see  #getDebugApblIfOn(CodeletInstance, String)
1104    * @see  #getDebugAptrIfOn(CodeletInstance, String)
1105    */
1106   public static final boolean isDebugOn(CodeletInstance instance, String name)  {
1107      return  getNamedDebuggers().isActive(name,
1108         getGlobalDebugLevel(), getInstanceDbgLevelOrNull(instance));
1109   }
1110   /**
1111      <p>If a named debuggers active, get an appendable.</p>
1112
1113    * @param  instance  May be {@code null}.
1114    * @return  <code>{@link #getNamedDebuggers() getNamedDebuggers}().{@link com.github.aliteralmind.codelet.util.NamedDebuggers#getAppendableIfActive(String, TextAppenter, DebugLevel, DebugLevel...) getAppendableIfActive}(name,
1115      <br/> &nbsp; &nbsp; {@link #getDebugAptr() getDebugAptr}(), {@link #getGlobalDebugLevel() getGlobalDebugLevel}(),
1116      <br/> &nbsp; &nbsp; instance.{@link CodeletInstance#getDebugLevel() getDebugLevel}()</code>
1117    * @see  #getDebugAptrIfOn(CodeletInstance, String)
1118    */
1119   public static final Appendable getDebugApblIfOn(CodeletInstance instance, String name)  {
1120      return  getNamedDebuggers().getAppendableIfActive(name,
1121         getDebugAptr(), getGlobalDebugLevel(),
1122         getInstanceDbgLevelOrNull(instance));
1123   }
1124   /**
1125      <p>If a named debuggers active, get an appenter.</p>
1126
1127    * @param  instance  May be {@code null}.
1128    * @return  <code>{@link #getNamedDebuggers() getNamedDebuggers}().{@link com.github.aliteralmind.codelet.util.NamedDebuggers#getAppenterIfActive(String, TextAppenter, DebugLevel, DebugLevel...) getAppenterIfActive}(name,
1129      <br/> &nbsp; &nbsp; {@link #getDebugAptr() getDebugAptr}(),
1130      <br/> &nbsp; &nbsp; {@link #getGlobalDebugLevel() getGlobalDebugLevel}(), instance.{@link CodeletInstance#getDebugLevel() getDebugLevel}()</code>
1131    * @see  #getDebugAptrIfOn(CodeletInstance, String)
1132    */
1133   public static final TextAppenter getDebugAptrIfOn(CodeletInstance instance, String name)  {
1134      return  getNamedDebuggers().getAppenterIfActive(name, getDebugAptr(),
1135         getGlobalDebugLevel(), getInstanceDbgLevelOrNull(instance));
1136   }
1137   /**
1138      <p>Directory containing the top-most package for the source code of all example classes.</p>
1139
1140    * @see  #EXAMPLE_CLASS_SRC_BASE_DIR
1141    */
1142   public static final String getExampleSourceBaseDir()  {
1143      return  xmplSrcBaseDir;
1144   }
1145   /**
1146      <p>An immutable list of all directories containing the <i>top-most package</i> of codelet-containing source-code.</p>
1147
1148    * @see  #ENCLOSING_CLASS_SRC_BASE_DIRS
1149    */
1150   public static final List<String> getEnclosingBaseDirList()  {
1151      return  enclosingBaseDirList;
1152   }
1153   static final String[] getEnclosingBaseDirs()  {
1154      return  enclosingBaseDirs;
1155   }
1156   /**
1157      <p>When <i>not</i> using a custom customizer (when using none, or a pre-made processor) how many spaces should all tabs be replaced with?.</p>
1158
1159    * @see  #DEFAULT_ALTERERS_CLASS_NAME
1160    */
1161   public static final DefaultAlterGetter getDefaultAlterGetter()  {
1162      return  defaultAlterGetter;
1163   }
1164   /**
1165      <p>The character placed immediately before gap names.</p>
1166
1167    * @see  #GAP_NAME_POSTFIX_CHAR
1168    */
1169   public static final GapCharConfig getGapCharConfig()  {
1170      return  gapCharConfig;
1171   }
1172   /**
1173      <p>The class that defines extra gaps that can be placed in Codelet templates.</p>
1174
1175    * @see  #USER_EXTRA_GAPS_CLASS_NAME
1176    */
1177   public static final String getUserExtraGapsClassName()  {
1178      return  userExtraGapsClassNm;
1179   }
1180   /**
1181      <p>The directory in which any custom (user-created) templates are stored.</p>
1182
1183    * @see  #USER_TEMPLATE_BASE_DIR
1184    */
1185   public static final String getCustomTemplateDir()  {
1186      return  customTmplDir;
1187   }
1188   /**
1189      <p>For determining which codelets should be processed or ignored.</p>
1190
1191    * @see  #BLACK_WHITE_LIST_TYPE
1192    */
1193   public static final FilenameBlackWhiteList getBlackWhiteList()  {
1194      return  blackWhiteList;
1195   }
1196   public static final int getTargetClassMapInitCapacity()  {
1197      return  jdTgtClsMapInitCapacity;
1198   }
1199   /**
1200      <p>If a customizer attempts to make an alteration, but cannot (such as when the find-what text is not found in the example code), what should happen?.</p>
1201
1202    * @return  <ul>
1203         <li>{@code true}: If a warning should be logged and an exception should be thrown.</li>
1204         <li>{@code false}: If only a warning should be logged.</li>
1205      </ul>
1206    * @see  #ALTERATION_NOT_MADE_CRASH
1207    */
1208   public static final boolean doCrashIfAlterationNotMade()  {
1209      return  doCrashIfAlterNotMade;
1210   }
1211   /**
1212      <p>How many attempts should be made to retrieve each online package-list? If zero, offline only.</p>
1213
1214    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
1215    */
1216   public static final int getOnlinePackageListAttemptCount()  {
1217      return  onlinePkgLstAttemptCount;
1218   }
1219   /**
1220      <p>How many milliseconds between each failed attempt?.</p>
1221
1222    * @see  #PKGLIST_ONLINE_ATTEMPT_SLEEP_MILLS
1223    */
1224   public static final long getOnlinePackageListAttemptSleepMills()  {
1225      return  onlinePkgLstAttemptSleepMills;
1226   }
1227   /**
1228      <p>If all online-retrieval attempts fail, should only a warning be logged, or should Codelet stop execution? (Offline package-lists are always retrieved.)</p>
1229
1230    * @see  #PKGLIST_ONLINE_FAILS_BEHAVIOR
1231    */
1232   public static final boolean doCrashIfOnlinePackageListFailure()  {
1233      return  doCrashIfOnlinePkgLstFails;
1234   }
1235   /**
1236      <p>When online {@code package-list}s are retrieved, should offline package lists be refreshed (or created)?</p>
1237
1238    * @see  #AUTO_UPDATE_OFFLINE_PACKAGE_LISTS
1239    */
1240   public static final boolean doAutoUpdateOfflinePackageLists()  {
1241      return  doAutoUpdateOfflinePkgLsts;
1242   }
1243   /**
1244      <p>The filename postfix, plus optional dot-extension that follows each offline name.</p>
1245
1246    * @see  #PKGLIST_OFFLINE_NAME_POSTFIX
1247    */
1248   public static final String getOfflinePackageListPostfix()  {
1249      return  offlinePkgLstNamePost;
1250   }
1251   /**
1252      <p>All external JavaDoc doc roots, for <a href="{@docRoot}/overview-summary.html#xmpl_links">creating links</a>.</p>
1253
1254    * @see  #PKGLIST_ONLINE_ATTEMPT_COUNT
1255    */
1256   public static final AllOnlineOfflineDocRoots getAllJavaDocRoots()  {
1257      return  allDocRoots;
1258   }
1259}