View Javadoc
1   /*
2    * The akquinet maven-latex-plugin project
3    *
4    * Copyright (c) 2011 by akquinet tech@spree GmbH
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package eu.simuline.m2latex.core;
20  
21  import java.io.BufferedReader;
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.InputStreamReader;
26  import java.io.PrintStream;
27  
28  import java.lang.reflect.Field;
29  import java.lang.reflect.InvocationTargetException;
30  import java.lang.reflect.Method;
31  import java.lang.reflect.Modifier;
32  
33  import java.util.List;
34  import java.util.ArrayList;
35  import java.util.Arrays;
36  
37  import java.util.Map;
38  import java.util.LinkedHashMap;
39  // import java.util.TreeMap;
40  import java.util.Set;
41  import java.util.SortedSet;
42  import java.util.TreeMap;
43  import java.util.HashSet;
44  import java.util.TreeSet;
45  
46  import com.florianingerl.util.regex.Matcher;
47  import com.florianingerl.util.regex.Pattern;
48  
49  // import java.lang.annotation.Annotation;
50  
51  
52  import org.apache.commons.text.StringEscapeUtils;
53  import org.apache.maven.plugins.annotations.Parameter;
54  // import org.apache.maven.plugin.descriptor.Parameter;
55  
56  // is AbstractLatexMojo but not public
57  import eu.simuline.m2latex.mojo.CfgLatexMojo;// for javadoc only
58  import eu.simuline.m2latex.mojo.InjectionMojo;// for javadoc only
59  
60  /**
61   * The settings for a maven plugin and for an ant task.
62   * These are the elements of the maven pom in element <code>settings</code>
63   * and accordingly for the ant build file.
64   * <p>
65   * For the options we have the contract,
66   * that in the initial value they are trimmed and separated by a single blank.
67   * The setter methods are so that before setting the new value is trimmed
68   * and multiple whitespaces are replaced by a single blank.
69   */
70  public class Settings {
71  
72    // static initializer 
73  
74    /**
75     * The name of the property of the parameter {@link InjectionMojo#injections}. 
76     */
77    public static final String PARAM_PROP = "latex.injections";
78  
79    /**
80     * Name of the group in {@link #PATTERN_CONFIG} 
81     * holding name of parameter or of getter method. 
82     */
83    private static final String GRP_NAME = "name";
84  
85    /**
86     * Name of he group in {@link #PATTERN_CONFIG} 
87     * holding <code>()</code> after name 
88     * which, if present 
89     * indicates that the name refers to a method; 
90     * else it refers to a field. 
91     */
92    private static final String GRP_METHOD = "method";
93  
94  
95    /**
96     * Pattern for names of parameters and getter methods 
97     * annotated {@link RuntimeParameter} 
98     * used in 
99     * {@link #filterInjection(InputStream,PrintStream,String,Injection)} 
100    * to filter resources for injection. 
101    * It contains two groups, one, named {@link #GRP_NAME} holding the name, 
102    * either of a field or of a method 
103    * and the other, optional group named {@link #GRP_METHOD} holding <code>()</code> 
104    * indicating a method rather than a field. 
105    */
106   private static final String PATTERN_CONFIG =
107     "\\$\\{(?<" + GRP_NAME + ">\\w+)(?<" + GRP_METHOD + ">\\(\\))?\\}";
108 
109 
110 
111   /**
112    * On unix <code>src/site/tex</code>, 
113    * on other operating systems accordingly. 
114    */
115   final static String SST;
116 
117   /**
118    * Identifier for a group. 
119    * For Perl it is <code>$</code> whereas for Lua it is <code>%</code>. 
120    * If splitindex shall be supported for both Perl and Lua, 
121    * then this must be configurable. 
122    */
123   final static String GRP_IDENT = "$";
124 
125   static {
126     String fs = System.getProperty("file.separator");
127     SST = "src" + fs + "site" + fs + "tex";
128   }
129 
130   // readonly parameters 
131 
132   /**
133    * The base directory of this maven project. 
134    * This shall be set only once through {@link #setBaseDirectory(File)} 
135    * in {@link eu.simuline.m2latex.mojo.AbstractLatexMojo#initialize()}. 
136    * It is not part of configuration in pom 
137    * but is filtered in {@link #filterInjection(InputStream, PrintStream, String, Injection)} 
138    * via {@link #getProperties()}. 
139    * Thus it is annotated as {@link RuntimeParameter}. 
140    * By constsruction this is without trailing file separator. 
141    * TBD: clarify: what about ant task? 
142    * TBD: improve design here. 
143    *
144    * @see CfgLatexMojo#baseDirectory
145    */
146   @RuntimeParameter
147   private File baseDirectory;
148 
149   /**
150    * The target directory of this maven project. 
151    * By default this is <code>{@link #baseDirectory}/target</code> 
152    * on Unix systems. 
153    *
154    * @see CfgLatexMojo#targetDirectory
155    */
156   private File targetDirectory;
157 
158   /**
159    * The target site directory of this maven project. 
160    * By default this is <code>{@link #targetDirectory}/site</code> 
161    * on Unix systems. 
162    *
163    * @see CfgLatexMojo#targetSiteDirectory
164    */
165   private File targetSiteDirectory;
166 
167   // read/write parameters and related. 
168   // If a parameter represents a relative path, this is a string 
169   // and there is an according field of type File. 
170 
171   /**
172    * The latex source directory as a string 
173    * relative to {@link #baseDirectory}, 
174    * containing {@link #texSrcProcDirectory}. 
175    * This directory determines also the subdirectory of 
176    * {@link #outputDirectory} to lay down the generated artifacts. 
177    * The according file is given by {@link #texSrcDirectoryFile}. 
178    * This must be without trailing file separator. 
179    * The default value is {@link #SST}. 
180    */
181   @RuntimeParameter
182   @Parameter(name = "texSrcDirectory",
183       defaultValue = "src${file.separator}site${file.separator}tex")
184   private String texSrcDirectory = SST;
185 
186   /**
187    * File for {@link #texSrcDirectory} based on {@link #baseDirectory}. 
188    */
189   private File texSrcDirectoryFile =
190     new File(this.texSrcDirectory);
191       //new File(this.baseDirectory, this.texSrcDirectory);
192 
193   /**
194    * The latex source processing directory as a string 
195    * relative to {@link #texSrcDirectory}
196    * containing all tex main documents 
197    * and the graphic files to be processed 
198    * and also to be cleaned. 
199    * Whether this is done recursively in subfolders 
200    * is specified by {@link #readTexSrcProcDirRec}. 
201    * The according file is given by {@link #texSrcProcDirectoryFile}. 
202    * The default value is <code>.</code>, 
203    * i.e. the latex souce processing directory is the latex source directory. 
204    */
205   @RuntimeParameter
206   @Parameter(name = "texSrcProcDirectory", defaultValue = ".")
207   private String texSrcProcDirectory = ".";
208 
209   /**
210    * File for {@link #texSrcProcDirectory} based on {@link #texSrcDirectory}. 
211    */
212   private File texSrcProcDirectoryFile =
213       new File(this.texSrcDirectoryFile, this.texSrcProcDirectory);
214 
215   /**
216    * Whether the tex source directory {@link #texSrcProcDirectory} 
217    * shall be read recursively for creation of graphic files, 
218    * i.e. including the subdirectories recursively. 
219    * This is set to <code>false</code> only during information development. 
220    * The default value is <code>true</code>. 
221    */
222   // FIXME: maybe in the long run: only latex main files. 
223   @RuntimeParameter
224   @Parameter(name = "readTexSrcProcDirRec", defaultValue = "true")
225   private boolean readTexSrcProcDirRec = true;
226 
227   /**
228    * The artifacts generated by {@link #latex2pdfCommand} 
229    * will be copied to this folder 
230    * which is given relative to {@link #targetSiteDirectory}. 
231    * The default value is <code>.</code>. 
232    * The according file is given by {@link #outputDirectoryFile}. 
233    *
234    * @see #texSrcDirectory
235    */
236   @RuntimeParameter
237   @Parameter(name = "outputDirectory", defaultValue = ".")
238   private String outputDirectory = ".";
239 
240   /**
241    * File for {@link #outputDirectory} based on {@link #targetSiteDirectory}. 
242    */
243   private File outputDirectoryFile =
244       new File(this.targetSiteDirectory, this.outputDirectory);
245 
246   /**
247    * Diff directory relative to {@link #baseDirectory} 
248    * used for diffing actually created artifacts 
249    * against prescribed ones in this directory. 
250    * This is relevant only if {@link #chkDiff} is set. 
251    * The according file is given by {@link #diffDirectoryFile}. 
252    * The default value is <code>src/main/resources/docsCmp</code>. 
253    * This must be without trailing file separator. 
254    */
255   @RuntimeParameter
256   @Parameter(name = "diffDirectory",
257   defaultValue = "src${file.separator}main${file.separator}resources${file.separator}docsCmp")
258   private String diffDirectory = "src/main/resources/docsCmp";
259 
260   /**
261    * File for {@link #diffDirectory} based on @link #baseDirectory}. 
262    */
263   private File diffDirectoryFile =
264       new File(this.baseDirectory, this.diffDirectory);
265 
266   /**
267    * A comma separated list of targets without blanks 
268    * returned as a set by {@link #getTargets()}. 
269    * For allowed values see {@link Target}. 
270    * <p>
271    * Independent of the order given, the given targets are created 
272    * in an internal ordering. 
273    * <p>
274    * Caution: These targets are the default targets for any latex main file, 
275    * but depending on the document class, there may be further restrictions 
276    * given by {@link #docClassesToTargets}. 
277    * Currently, only the class <code>beamer</code> has restrictions. 
278    * <p>
279    * The default value is <code>chk,pdf,html</code>. 
280    */
281   @RuntimeParameter
282   @Parameter(name = "targets", defaultValue = "chk,pdf,html",
283       property = "latex.targets") //
284   //private SortedSet<Target> targets;
285   private String targets = "chk,pdf,html";
286   // TBD: clarify why the following initialization causes that no goal descriptors are found. 
287   // = new TreeSet<Target>(Arrays.asList(new Target[] {Target.chk, Target.pdf, Target.html}));
288   // TBD: publish that giving the default value in the annotation works only within the lifecycle. 
289   // In contrast, if running on the command line as mvn latex:cfg, this does not work: no init: nullpointer. 
290   // maybe then we need as latex.targets 
291   // TBD: clarify whether it isn't better to specify the init value by annotation
292   // In old times targets was just a string and conversion to enum set was done internally. 
293   // TBD: clarify why latex.targets does not work either. 
294   // Thus the user cannot command `mvn latex:cfg -Dlatex.targets=pdf`: also nullpointer 
295   // maybe because inside the Settings. 
296 
297   /**
298    * A comma separated list of excluded {@link Converter}s 
299    * given by their command, i.e. by {@link Converter#getCommand()}
300    * returned as a set by {@link #getConvertersExcluded()}. 
301    * Excluded converters need not be installed but their names must be known. 
302    * They don't show up in the version check of target 'vrs' 
303    * and of course they are not allowed to be used. 
304    * By default, this list is empty. 
305    */
306   @RuntimeParameter
307   @Parameter(name = "convertersExcluded", defaultValue = "")
308   private String convertersExcluded = "";
309 
310   /**
311    * The pattern to be applied to the beginning of the contents of TEX-files 
312    * which identifies a latex main file and which extracts the document class 
313    * if the file is really a latex main file. 
314    * The default value is chosen to match quite exactly the start of 
315    * the latex main files. 
316    * Here we assume that the latex main file should contain 
317    * the declaration `\documentclass' 
318    * or the old fashioned `\documentstyle' 
319    * preceeded by a few constructs and followed by the documen class. 
320    * <p>
321    * Strictly speaking, a tight match is not necessary, 
322    * only separation of latex main files from other files is 
323    * and so is extraction of the document class. 
324    * For a more thorough discussion, 
325    * and for an alternative approach, consult the manual. 
326    * <p>
327    * Since the pattern is chosen 
328    * according to documentation collected from the internet, 
329    * one can never be sure whether the pattern is perfect. 
330    * <p>
331    * If the current default value is not appropriate, 
332    * please overwrite it in the configuration 
333    * and notify the developer of this plugin of the deficiency. 
334    * In any case, matching of the group named <code>class</code> must be retained 
335    * so that the document class is matched. 
336    * <p>
337    * Note that this pattern contains named groups 
338    * which are given by elements of {@link LatexMainParameterNames}. 
339    */
340   // One shall use LatexMainParameterNames to fill in the names of the named groups. 
341   // FIXME: not only on this pattern: 
342   // Matching is line by line which is inappropriate. 
343   // pattern is to be applied to the start of the tex-file 
344   // FIXME: I have the impression, that the concept we use is not very good. 
345   // Maybe one has to use a magic comment to identify latex main files. 
346   // There is a tendency to allow even more in the header with coming releases of latex 
347   @RuntimeParameter
348   @Parameter(name = "patternLatexMainFile")
349   // Note that \DocumentMetadata must be first of the commands 
350   // but this need not be reflected by this pattern. 
351   // This is an example for a recursive pattern 
352   private String patternLatexMainFile =
353   """
354   \\A\
355   (%\\s*!\\s*T[eE]X (TXS|spellcheck|encoding|root).*\\R)*\
356   (%\\s*!\\s*T[eE]X program\\s*=\\s*(?<programMagic>[^} ]+)\\R)?\
357   (%\\s*!\\s*T[eE]X .*\\R)*\
358   (%\\s*!\\s*LMP (?<chkDiffMagic>chkDiff)(=(?<chkDiffMagicVal>true|false))?\\R)?\
359   (%\\s*!\\s*LMP (?<latexmkMagic>latexmk)(=(?<latexmkMagicVal>true|false))?\\R)?\
360   (%\\s*!\\s*LMP targets=(?<targetsMagic>(\\p{Lower}|,)+)\\R)?\
361   (\\s*(\
362   \\\\RequirePackage\\s*(\\[(\\s|\\w|[,=])*\\])?\\s*\\{(\\w|-)+\\}\\s*(\\[(\\d|[-./])+\\])?|\
363   \\\\PassOptionsToPackage\\s*\\{(\\s|\\w|[,=])*\\}\\s*\\{(\\w|-)+\\}|\
364   \\\\newbool\\s*\\{\\w+\\}|\
365   \\\\setbool\\s*\\{\\w+\\}\\{(true|false)\\}|\
366   \\\\DocumentMetadata(?<docMetadata>\\{(?:[^{}]|(?'docMetadata'))*\\})|\
367   \\\\input\\s*\\{[^{}]*\\}\
368   )?\\s*(%.*)?\\R)*\
369   \\\\(documentstyle|documentclass)\\s*(\\[[^]]*\\])?\\s*\\{(?<docClass>[^} ]+)\\}\
370   """;
371   //"\\\\newbool\\s*\\{(\\w)+\\}\\s*|" + // newbool
372   //"\\\\setbool\\s*\\{(\\w)+\\}\\{(true|false)\\}\\s*|" + // setbool only with literal values 
373 
374   /**
375    * Assigns to document classes their allowed {@link #targets}. 
376    * The map expression is a list of chunks separated by a single blank. 
377    * Each chunk is divided by a single colon 
378    * in a comma separated list of document classes, 
379    * and a comma separated list of targets. 
380    * <p>
381    * A chunk means that all given document classes are compiled for the given targets. 
382    * Thus, the set of document classes may not be empty, 
383    * i.e. the colon may not be at the first place of its chunk. 
384    * In contrast, a colon at the last place of a chunk indicates an empty target set, 
385    * meaning that documents of the given class are not processed at all. 
386    * <p>
387    * The document classes of the chunks may not overlap. 
388    * A document of a class is compiled for a target if this is specified so by a chunk. 
389    * <p>
390    * As a side effect, compilation of document classes cause warnings if not registered here. 
391    * The default value consists of two chunks: 
392    * <ul>
393    * <li><tt>article,report,book,minimal:chk,dvi,pdf,html,odt,docx,rtf,txt</tt> 
394    * ensures that article and book allow all targets. </li>
395    * <li><tt>beamer,leaflet,scrlttr2:chk,pdf,txt</tt> beamer allows mainly pdf and derived from that txt. 
396    * Checking with chk does not depend on the document class. 
397    * Note that maybe leaflets or letters may work in DVI or XDV also an even for word formats and related, 
398    * we restrict ourselves to the given output for simplification. </li>
399    * </ul>
400    */
401   @RuntimeParameter
402   @Parameter(name = "docClassesToTargets")
403   private String docClassesToTargets =
404       "article,report,book,minimal:chk,dvi,pdf,html,odt,docx,rtf,txt\nbeamer,leaflet,scrlttr2:chk,pdf,txt";
405 
406   /**
407    * The list of names of latex main files 
408    * without extension <code>.tex</code> 
409    * separated by whitespace 
410    * which shall be included for creating targets, 
411    * except if this is empty in which cases all are included. 
412    * It is assumed that the names of the latex main files 
413    * do not contain whitespace. 
414    * Note that leading and trailing whitespace are trimmed. 
415    * Currently, 
416    * names of latex main files should better have pairwise different names, 
417    * even if in different directories. 
418    * <p>
419    * The empty string is the default, i.e. including all. 
420    * 
421    * @see #mainFilesExcluded
422    */
423   @RuntimeParameter
424   @Parameter(name = "mainFilesIncluded", defaultValue = "")
425   private String mainFilesIncluded = "";
426 
427 
428   /**
429    * The list of names of latex main files 
430    * without extension <code>.tex</code> 
431    * separated by whitespace 
432    * which shall be excluded for creating targets. 
433    * It is assumed that the names of the latex main files 
434    * do not contain whitespace. 
435    * Note that leading and trailing whitespace are trimmed. 
436    * Currently, 
437    * names of latex main files should better have pairwise different names, 
438    * even if in different directories. 
439    * <p>
440    * Together with {@link #mainFilesIncluded}, 
441    * this is used for document development 
442    * to build the pdf of a subset of documents 
443    * and e.g. because for a site one needs all documents, 
444    * but with the software only the manual is shipped. 
445    * The empty string is the default, i.e. excluding no file. 
446    * 
447    * @see #mainFilesIncluded
448    */
449   @RuntimeParameter
450   @Parameter(name = "mainFilesExcluded", defaultValue = "")
451   private String mainFilesExcluded = "";
452 
453   /**
454    * The extent to which latexmk or to be more precise, 
455    * the command given by {@link #latexmkCommand} is used to build. 
456    * This setting can be overwritten for individual latex main files 
457    * by the magic comment represented by {@link LatexMainParameterNames#latexmkMagic}. 
458    * The default is {@link LatexmkUsage#NotAtAll}. 
459    */
460   @RuntimeParameter
461   @Parameter(name = "latexmkUsage", defaultValue = "NotAtAll")
462   private LatexmkUsage latexmkUsage = LatexmkUsage.NotAtAll;
463 
464   // texPath, commands and arguments 
465 
466   /**
467    * Path to the TeX scripts or <code>null</code>. 
468    * In the latter case, the scripts must be on the system path. 
469    * Note that in the pom, <code>&lt;texPath/&gt;</code> 
470    * and even <code>&lt;texPath&gt;    &lt;/texPath&gt;</code> 
471    * represent the <code>null</code>-File. 
472    * The default value is <code>null</code>. 
473    */
474   // TBD: clarify whether null as defaultValue works properly 
475   @RuntimeParameter
476   @Parameter(name = "texPath", defaultValue = "null")
477   private File texPath = null;
478 
479   // TBD: update documentation 
480   /**
481    * Indicates whether after creating artifacts 
482    * and copying them to the output directory {@link #outputDirectoryFile} 
483    * the artifacts are checked by diffing them against preexisting artifacts 
484    * in {@link #diffDirectoryFile} 
485    * using the diff command given by {@link #diffPdfCommand}. 
486    * If this is set, the system time is set to 0 indicating 1970--01--01. 
487    * Note that currently, only pdf files are checked. 
488    * This setting can be overwritten for individual latex main files 
489    * as described by {@link LatexMainParameterNames#chkDiffMagic}. 
490    * This is <code>false</code> by default and is set to <code>true</code> only 
491    * in the context of tests. 
492    */
493   @RuntimeParameter
494   @Parameter(name = "chkDiff", defaultValue = "false")
495   private boolean chkDiff = false;
496 
497   /**
498    * Clean up the working directory in the end? 
499    * May be used for debugging when setting to <code>false</code>. 
500    * The default value is <code>true</code>. 
501    */
502   @RuntimeParameter
503   @Parameter(name = "cleanUp", defaultValue = "true")
504   private boolean cleanUp = true;
505 
506   // TBD: pythontex-files-T$T occurs here but also in parameter 
507   /**
508    * This pattern is applied to file names 
509    * and matching shall accept all the files 
510    * which were created from a latex main file <code>xxx.tex</code>. 
511    * It is neither applied to directories 
512    * nor to <code>xxx.tex</code> itself. 
513    * It shall not comprise neither graphic files to be processed 
514    * nor files created from those graphic files. 
515    * <p>
516    * This pattern is applied 
517    * in the course of processing graphic files 
518    * to decide which graphic files should be processed 
519    * (those rejected by this pattern) 
520    * and to log warnings if there is a risk, 
521    * that graphic files to be processed 
522    * are skipped or that processing a latex main file overwrites 
523    * the result of graphic preprocessing. 
524    * <p>
525    * When clearing the tex source directory {@link #texSrcProcDirectory}, 
526    * i.e. all generated files should be removed, 
527    * first those created from latex main files. 
528    * As an approximation, 
529    * those are removed which match this pattern. 
530    * <p>
531    * The sequence <code>T$T</code> 
532    * is replaced by the prefix <code>xxx</code>. 
533    * The sequence <code>T$T</code> must always be replaced: 
534    * The symbol <code>$</code> occurs as end-sign as <code>)$</code> 
535    * or as literal symbol as <code>\$</code>. 
536    * Thus <code>T$T</code> is no regular occurrence 
537    * and must always be replaced with <code>xxx</code>. 
538    * <p>
539    * Spaces and newlines are removed 
540    * from that pattern before matching. 
541    * <p>
542    * This pattern may never be ensured to be complete, 
543    * because any package 
544    * may create files with names matching its own patterns 
545    * and so any new package may break completeness. 
546    * <p>	 
547    * If the current default value is not appropriate, 
548    * please overwrite it in the configuration 
549    * and notify the developer of this plugin of the deficiency. 
550    * The default value is given below. 
551    */
552   @RuntimeParameter
553   @Parameter(name = "patternCreatedFromLatexMain")
554   private String patternCreatedFromLatexMain =
555       // besides T$T.xxx, with xxx not containing ., 
556       // we allow T$T.synctex.gz and T$T.out.ps 
557       "^(T$T(\\.([^.]*|synctex(\\(busy\\))?(\\.gz)?|" + // synctex
558           "out\\.ps|run\\.xml|\\d+\\.vrb|depytx(\\.tex)?)|" + // out? beamer, pythontex 
559           // tex4ht creates files T$Tyy.(x)htm(l)... 
560           "(-|ch|se|su|ap|li)?\\d+\\.x?html?|" +
561           // ... and T$Tddx.(x)bb, T$Tddx.png and T$T-dd.svg... 
562           "\\d+x\\.x?bb|" + "\\d+x?\\.png|" + "-\\d+\\.svg|" +
563           // by (splitidx and) splitindex 
564           // TBD: check: formerly was ...ilg)| which allows also T$T itself! 
565           // If a file test.tex is a latex main file and there is a folder with the same name, 
566           // then the folder is deleted even if not empty. 
567           // Thus removed the trailing '|'
568           "-.+\\.(idx|ind|ilg)" + ")|" + // end all patterns starting with T$T
569           // created by pythontex
570           "pythontex-files-T$T|" + // folders from package pythontex
571           // ... and xxT$T.eps... 
572           "zzT$T\\.e?ps|" +
573           // ... and scripts cmsy....png 
574           "(cmsy)\\d+(-c)?-\\d+c?\\.png|" +
575           // The following occurs sporadic when using latexmk 
576           "(pdf|xe|lua)?latex\\d+\\.fls|" +
577           // created by package pdfx or with \DocumentMetadata
578           "pdf[xae]\\.xmpi?|" +
579           // Seemingly for errors 
580           "texput\\.(fls|log))$";
581 
582 
583   // parameters for graphics preprocessing 
584 
585 
586   /**
587    * The fig2dev command for conversion of fig-files 
588    * into various formats. 
589    * Currently only pdf combined with pdf_t is supported. 
590    * Note that preprocessing one fig-file 
591    * requires two invocations of {@link #fig2devCommand}, 
592    * one for each part. 
593    * The default value is <code>fig2dev</code>. 
594    *
595    * @see #fig2devGenOptions
596    * @see #fig2devPtxOptions
597    * @see #fig2devPdfEpsOptions
598    */
599   @RuntimeParameter
600   @Parameter(name = "fig2devCommand", defaultValue = "fig2dev")
601   private String fig2devCommand = "fig2dev";
602 
603   /**
604    * The options for the command {@link #fig2devCommand} 
605    * common to both output languages. 
606    * For the options specific for the two output langugages 
607    * <code>pdftex</code> and <code>pdftex_t</code>, 
608    * see {@link #fig2devPtxOptions} and {@link #fig2devPdfEpsOptions}, 
609    * respectively. 
610    * The default value is the empty string. 
611    * <p>
612    * Possible are the following options: 
613    * <ul>
614    * <li><code>-D +/-rangelist</code> 
615    * Export layers selectively (<code>+</code>) 
616    * or exclude layers from export (<code>-</code>). 
617    * E.g. -D +10,40,55:70,80  means  keep 
618    * only layers 10, 40, 55 through 70, and 80.
619    * <li><code>-j</code> 
620    * i18n (internationalization feature)
621    * <li><code>-m mag</code> 
622    * Set the magnification at which the figure is rendered 
623    * to <code>mag</code>.
624    * The default is <code>1.0</code>. 
625    * This is not usable within latex; not even <code>1.0</code>. 
626    * <li><code>-s fsize</code> 
627    * Set the default font size (in points) 
628    * for text objects to <code>fsize</code>.
629    * Refers to the latex-fonts only. 
630    * <li><code>-b width</code> 
631    * specify width of blank border around figure (1/72 inch). 
632    * </ul>
633    * Except for the option <code>-j</code>, 
634    * all these options take parameters 
635    * and it may make sense to use them with different parameters 
636    * for the two output languages. 
637    * In this case include them in 
638    * {@link #fig2devPtxOptions} and in {@link #fig2devPdfEpsOptions}. 
639    */
640   @RuntimeParameter
641   @Parameter(name = "fig2devGenOptions", defaultValue = "")
642   private String fig2devGenOptions = "";
643 
644   /**
645    * The options for the command {@link #fig2devCommand} 
646    * specific for the output languages <code>pdftex_t</code> 
647    * and <code>pstex_t</code> which are the same. 
648    * Note that in addition to these options, 
649    * the option <code>-L pdftex_t</code> specifies the language, 
650    * {@link #fig2devGenOptions} specifies the options 
651    * common for the two output langugages 
652    * <code>pdftex</code> and <code>pdftex_t</code> 
653    * and <code>-p xxx</code> specifies the full path 
654    * of the pdf/eps-file to be included without extension. 
655    * <p>
656    * The default value for this option is the empty string. 
657    * <p>
658    * Possible options are the following: 
659    * (These seem to work for tex only 
660    * although according to documentation for all languages. )
661    * <ul>
662    * <li> options specified for {@link #fig2devGenOptions} 
663    * <li> <code>-E num</code>
664    * Set encoding for latex text translation 
665    * (0 no translation, 1 ISO-8859-1, 2 ISO-8859-2), 
666    * others allowed also, effect not clear. 
667    * <li> <code>-F</code>  
668    * don't set font family/series/shape, 
669    * so you can set it from latex. 
670    * <li> <code>-v</code>
671    * Verbose mode.
672    * </ul>
673    */
674   // Note that several options do not make sense as global options, 
675   // better as individual options. 
676   // Maybe it makes sense, to include those options 
677   // in the fig-file and use a wrapper around fig2dev 
678   // instead of fig2dev itself, 
679   // which invokes fig2dev with the according options. 
680   // Problem is that xfig does not support this. 
681   @RuntimeParameter
682   @Parameter(name = "fig2devPtxOptions", defaultValue = "")
683   private String fig2devPtxOptions = "";
684 
685   /**
686    * The options for the command {@link #fig2devCommand} 
687    * specific for the output language <code>pdftex</code>. 
688    * Note that in addition to these options, 
689    * the option <code>-L pdftex</code> specifies the language and 
690    * {@link #fig2devGenOptions} specifies the options 
691    * common for the two output langugages 
692    * <code>pdftex</code> and <code>pdftex_t</code>. 
693    * The default value for this option is the empty string. 
694    * <p>
695    * Possible options are the following: 
696    * (These seem to work specifically for pdf 
697    * although according to documentation for all languages. )
698    * <ul>
699    * <li> options specified for {@link #fig2devGenOptions} 
700    * <li> <code>-G minor[:major][unit]</code>
701    * Draws a grid on the page.  
702    *    e.g. "-G .25:1cm" draws a thin line every .25 cm 
703    *    and a thicker line every 1 cm. 
704    *    Default unit is in.  
705    *    Allowable units are: 
706    *    i, in, inch, f, ft, feet, c, cm, mm, and m. 
707    * <li> <code>-A</code>
708    * Add an ASCII (EPSI) preview.
709    * <li> <code>-c</code>
710    * centers the figure on the page.  (default)
711    * seems not to have an effect...
712    * <li> <code>-e</code>
713    * puts the  figure against the edge (not centered) of the page. 
714    * seems not to have an effect...
715    * <li> <code>-F</code>
716    * Use correct font sizes (points) instead of the traditional  size
717    * <li> <code>-g color</code>
718    * Use color for the background. 
719    * FIXME: Not clear how to specify the color. 
720    * <li> <code>-N</code>
721    * Convert all colors to grayscale. (not available for latex fonts)
722    * <li> <code>-n name</code>
723    * Set  the /Title(xxx) of the PostScript output to <code>name</code>. 
724    * without it is just the filename <code>xxx.fig</code>. 
725    */
726   // Note that several options do not make sense as global options, 
727   // better as individual options. 
728   // Maybe it makes sense, to include those options 
729   // in the fig-file and use a wrapper around fig2dev 
730   // instead of fig2dev itself, 
731   // which invokes fig2dev with the according options. 
732   // Problem is that xfig does not support this. 
733   @RuntimeParameter
734   @Parameter(name = "fig2devPdfEpsOptions", defaultValue = "")
735   private String fig2devPdfEpsOptions = "";
736 
737   /**
738    * The command for conversion of gnuplot-files 
739    * into various formats. 
740    * Currently only pdf (graphics) 
741    * combined with pdf_t (latex-texts) is supported. 
742    * The default value is <code>gnuplot</code>. 
743    */
744   @RuntimeParameter
745   @Parameter(name = "gnuplotCommand", defaultValue = "gnuplot")
746   private String gnuplotCommand = "gnuplot";
747 
748   /**
749    * The options specific for {@link #gnuplotCommand}'s 
750    * output terminal <code>cairolatex</code>, 
751    * used for mixed latex/pdf-creation. 
752    * <p>
753    * Possible values are: 
754    * <ul>
755    * <li><code>{standalone | input}</code>
756    * <li><code>{blacktext | colortext | colourtext}</code>
757    * Specifies whether for text colors are taken into account or not. 
758    * For all but text see separate options. 
759    * <li><code>{header <header> | noheader}</code>
760    * <li><code>{mono|color}</code>
761    * Specifies whether colors are taken into account or not. 
762    * Refers to all but text (for text see separate options)
763    * <li><code>{{no}transparent} {{no}crop} {background <rgbcolor>}</code>
764    * <li><code>{font <font>}</code>
765    * <li><code>{fontscale <scale>}</code>
766    * <li><code>{linewidth <lw>} {rounded|butt|square} {dashlength <dl>}</code>
767    * <li><code>{size <XX>{unit},<YY>{unit}}</code>
768    * The size of this picture. 
769    * This is not usable, because it imposes deformation. 
770    * Default unit is inch (<code>in</code>). 
771    * </ul>
772    * Note that the option <code>pdf|eps</code> 
773    * of the terminal <code>cairolatex</code> is not available, 
774    * because it is set internally. 
775    * The default option string is empty. 
776    */
777   @RuntimeParameter
778   @Parameter(name = "gnuplotOptions", defaultValue = "")
779   private String gnuplotOptions = "";
780 
781   /**
782    * The command for conversion of gnuplot-files 
783    * into metapost's postscript. 
784    * The default value is <code>mpost</code>. 
785    */
786   @RuntimeParameter
787   @Parameter(name = "metapostCommand", defaultValue = "mpost")
788   private String metapostCommand = "mpost";
789 
790   /**
791    * The options for the command {@link #metapostCommand}. 
792    * Leading and trailing blanks are ignored. 
793    * A sequence of at least one blank separate the proper options. 
794    * The default value comprises the following options: 
795    * <ul>
796    * <li><code>-interaction=nonstopmode</code> 
797    * prevents metapost from stopping at the first error. 
798    * <li><code>-recorder</code> 
799    * makes metapost create an fls-file specifying all inputted files. 
800    * <li><code>-s prologues=2</code> 
801    * makes metapost create a postscript file 
802    * which is viewable by ghostscript viewer.
803    * </ul>
804    * 
805    * -debug creates intermediate files mp3mnuvD.dvi and mp3mnuvD.tex 
806    * No info available about the details. 
807    */
808   @RuntimeParameter
809   @Parameter(name = "metapostOptions",
810       defaultValue = "-interaction=nonstopmode -recorder "
811           + "-s prologues=2 -s outputtemplate=\"%j.mps\"")
812   private String metapostOptions =
813       "-interaction=nonstopmode -recorder -s prologues=2 -s outputtemplate=\"%j.mps\"";
814 
815   /**
816    * The pattern is applied line by line to the log-file of mpost 
817    * and matching indicates an error 
818    * emitted by the command {@link #metapostCommand}. 
819    * <p>
820    * The default value is chosen to match quite exactly 
821    * the latex errors in the log file, no more no less. 
822    * Since no official documentation was found, 
823    * the default pattern may be incomplete. 
824    * In fact, it presupposes, that {@link #metapostOptions} 
825    * does not contain `<code>-file-line-error-style</code>'.   
826    * <p>
827    * If the current default value is not appropriate, 
828    * please overwrite it in the configuration 
829    * and notify the developer of this plugin of the deficiency. 
830    * The default value is `<code>(^! )</code>' (note the space). 
831    */
832   // FIXME: Problem with line error style 
833   @RuntimeParameter
834   @Parameter(name = "patternErrMPost", defaultValue = "(^! )")
835   private String patternErrMPost = "(^! )";
836 
837   /**
838    * The pattern is applied line by line to the log-file of mpost 
839    * and matching indicates a warning 
840    * emitted by the command {@link #metapostCommand}. 
841    * <p>
842    * This pattern may never be ensured to be complete, 
843    * because any library may indicate a warning 
844    * with its own pattern any new package may break completeness. 
845    * Nevertheless, the default value aims completeness 
846    * while be restrictive enough 
847    * not to indicate a warning where none was emitted. 
848    * <p>
849    * If the current default value is not appropriate, 
850    * please overwrite it in the configuration 
851    * and notify the developer of this plugin of the deficiency. 
852    * The default value is given below. 
853    */
854   // mpost --no-parse-first-line yields 
855   // warning: mpost: unimplemented option
856   @RuntimeParameter
857   @Parameter(name = "patternWarnMPost", defaultValue = "^([Ww]arning: )")
858   private String patternWarnMPost = "^([Ww]arning: )";
859 
860   /**
861    * The command for conversion of svg-files 
862    * into a mixed format FIXME, synchronize with fig2devCommand. 
863    * The default value is <code>inkscape</code>. 
864    */
865   @RuntimeParameter
866   @Parameter(name = "svg2devCommand", defaultValue = "inkscape")
867   private String svg2devCommand = "inkscape";
868 
869   /**
870    * The options for the command {@link #svg2devCommand} 
871    * for exporting svg-figures into latex compatible files. 
872    * <p>
873    * The following options are mandatory: 
874    * <ul>
875    * <li><code>-D</code> or <code>--export-area-drawing</code> 
876    * Export the drawing (not the page)
877    * <li><code>--export-latex</code> 
878    * Export PDF/PS/EPS without text. 
879    * Besides the PDF/PS/EPS, a LaTeX file is exported,
880    * putting the text on top of the PDF/PS/EPS file. 
881    * Include the result in LaTeX like: \input{latexfile.tex}. 
882    * Note that the latter option is necessary, 
883    * to create the expected files. 
884    * It is also conceivable to export text as pdf/eps 
885    * </ul>
886    * <p>
887    * The following options are prohibited, 
888    * because they are automatically added by the software 
889    * or are in conflict with automatically added options: 
890    * <ul>
891    * <li><code>--export-filename=FILENAME</code>
892    * <li><code>--export-type=type</code> 
893    * <ul>
894    *
895    * The default value is the minimal value, 
896    * <code>--export-area-drawing --export-latex</code>. 
897    */
898   @RuntimeParameter
899   @Parameter(name = "svg2devOptions",
900       defaultValue = "--export-area-drawing --export-latex")
901   private String svg2devOptions = "--export-area-drawing --export-latex";
902 
903   /**
904    * Whether for pixel formats like jpg and png 
905    * command {@link #ebbCommand} is invoked to determine the bounding box. 
906    * This is relevant, if at all, only in dvi-mode. 
907    * Note that the package <code>bmpsize</code> is an alternative 
908    * to invoking the {@link #ebbCommand}, 
909    * which seems not to work for xelatex. 
910    * Moreover, all seems to work fine with neither of these techniques. 
911    * The {@link #dvi2pdfCommand} given by the default, <code>dvipdfmx</code>, 
912    * seems the only which yields the picture sizes as in PDF mode 
913    * which fit well. 
914    * 
915    * In 2025 the author realized that the {@link #ebbCommand} <code>ebb</code> 
916    * was in fact replaced by <code>extractbb</code> 
917    * and the original command <code>ebb</code> survived just as a link.
918    * Note also that miktex does not offer neither package <code>bmpsize</code> 
919    * nor <code>e(xtract)bb</code>. 
920    * This alone requires to switch off invocation of <code>e(xtract)bb</code> by default. 
921    * So the default value is <code>false</code>. 
922    */
923   @RuntimeParameter
924   @Parameter(name = "createBoundingBoxes", defaultValue = "false")
925   private boolean createBoundingBoxes = false;
926 
927   /**
928    * The command to create bounding box information 
929    * from jpg-files and from png-files. 
930    * This is run twice: 
931    * once with parameter <code>-m</code> 
932    * to create <code>.bb</code>-files for driver <code>dvipdfm</code> and 
933    * once with parameter <code>-x</code> 
934    * to create <code>.xbb</code>-files for driver <code>dvipdfmx</code>. 
935    * The default value is <code>extractbb</code> 
936    * but maybe the installation requires the original <code>ebb</code>. 
937    */
938   @RuntimeParameter
939   @Parameter(name = "ebbCommand", defaultValue = "extractbb")
940   private String ebbCommand = "extractbb";
941 
942   /**
943    * The options for the command {@link #ebbCommand} 
944    * except <code>-m</code> and <code>-x</code> 
945    * which are added automatically. 
946    * The default value is <code>-v</code> to make <code>e(xtract)bb<code> verbose. 
947    */
948   // without -x and -m 
949   @RuntimeParameter
950   @Parameter(name = "ebbOptions", defaultValue = "-v")
951   private String ebbOptions = "-v";
952 
953   // parameters for latex2pdf-conversion 
954 
955   /**
956    * The LaTeX command to create above all a pdf-file with, 
957    * but also dvi and other formats based on these. 
958    * Expected values are 
959    * <code>lualatex</code> <code>xelatex</code>, and <code>pdflatex</code>. 
960    * <p>
961    * Note that for <code>xelatex</code> dvi mode 
962    * (creating xdv-files instead of dvi-files) is not supported, 
963    * even not creating pdf or other formats via xdv. 
964    * See also the according options {@link #latex2pdfOptions} 
965    * and {@link #pdfViaDvi}. 
966    * In particular, for <code>xelatex</code> 
967    * this maven plugin does not allow goal <code>dvi</code> and related. 
968    * Consequently, {@link #targets} may not contain any of these goals. 
969    * The default value (for which this software is also tested) 
970    * is <code>lualatex</code>.
971    */
972   @RuntimeParameter
973   @Parameter(name = "latex2pdfCommand", defaultValue = "lualatex")
974   private String latex2pdfCommand = "lualatex";
975 
976   // // TBD: this may well be null 
977   // // used in LatexProcessor.runLatex2dev to find out whether 
978   // // - xelatex (option -no-pdf) or 
979   // // - lualatex or pdflatex (option -output-format=dvi or pdf)
980   // // - something unknown. 
981   // // depends on the 
982   // Converter latex2pdfType = Converter.cmd2Conv(latex2pdfCommand);
983 
984   // enum LatexConverterType {
985   //   Xdv, Dvi, Invalid;
986   //   // String target2Option(Target target) {
987   //   //   switch (target)
988   //   // }
989   // }
990 
991   /**
992    * The options for the command {@link #latex2pdfCommand}. 
993    * Leading and trailing blanks are ignored. 
994    * The setter method {@link #setLatex2pdfOptions(String)} ensures, 
995    * that exactly one blank separate the proper options. 
996    * <p>
997    * The default value comprises the following options: 
998    * <ul>
999    * <li><code>-interaction=nonstopmode</code> 
1000    * prevents latex from stopping at the first error. 
1001    * <li><code>-synctex=1</code> 
1002    * makes latex create a pdf file 
1003    * which synchronizes with an editor supporting synchtex. 
1004    * <li><code>-recorder</code> 
1005    * makes latex create an fls-file specifying all inputted files. 
1006    * <li><code>-shell-escape</code> 
1007    * allows to use write18-mechanism for shell commands (why needed?)
1008    * </ul>
1009    * Note that several options offered by some latex converters 
1010    * are not allowed for this software. 
1011    * For details consult the manual. 
1012    */
1013   // useful also: -file-line-error
1014   @RuntimeParameter
1015   @Parameter(name = "latex2pdfOptions",
1016       defaultValue = "-interaction=nonstopmode " + // 
1017           "-synctex=1 " + "-recorder " + "-shell-escape")
1018   private String latex2pdfOptions = "-interaction=nonstopmode " + // 
1019       "-synctex=1 " + "-recorder " + "-shell-escape";
1020 
1021   /**
1022    * The pattern is applied line by line to the log-file 
1023    * and matching indicates an error 
1024    * emitted by the command {@link #latex2pdfCommand}. 
1025    * <p>
1026    * The default value is chosen to match quite exactly 
1027    * the latex errors in the log file, no more no less. 
1028    * Since no official documentation was found, 
1029    * the default pattern may be incomplete. 
1030    * In fact, it presupposes, that {@link #latex2pdfOptions} 
1031    * does not contain `<code>-file-line-error-style</code>'.   
1032    * <p>
1033    * If the current default value is not appropriate, 
1034    * please overwrite it in the configuration 
1035    * and notify the developer of this plugin of the deficiency. 
1036    * The default value is `<code>(^! )</code>' (note the space). 
1037    */
1038   // FIXME: Problem with line error style 
1039   @RuntimeParameter
1040   @Parameter(name = "patternErrLatex", defaultValue = "(^! )")
1041   private String patternErrLatex = "(^! )";
1042 
1043   /**
1044    * The pattern is applied line by line to the log-file 
1045    * and matching indicates a warning 
1046    * emitted by the command {@link #latex2pdfCommand}, 
1047    * disragarding warnings on bad boxes 
1048    * provided {@link #debugWarnings} is set. 
1049    * <p>
1050    * This pattern may never be ensured to be complete, 
1051    * because any package may indicate a warning 
1052    * with its own pattern any new package may break completeness. 
1053    * Nevertheless, the default value aims completeness 
1054    * while be restrictive enough 
1055    * not to indicate a warning where none was emitted. 
1056    * <p>
1057    * If the current default value is not appropriate, 
1058    * please overwrite it in the configuration 
1059    * and notify the developer of this plugin of the deficiency. 
1060    * The default value is given below. 
1061    *
1062    * @see #debugBadBoxes
1063    */
1064   @RuntimeParameter
1065   @Parameter(name = "patternWarnLatex", defaultValue = "^(LaTeX Warning: |"
1066       + "LaTeX Font Warning: |"
1067       + "(Package|Class) .+ Warning: |"
1068       // pdftex warning (ext4): destination with the same identifier
1069       // pdfTeX warning (dest): ... has been referenced ...
1070       // pdfTeX warning: pdflatex (file pdftex.map): cannot open font map file 
1071       // pdfTeX warning: Found pdf version 1.5, allowed maximum 1.4 
1072       // pdfTeX warning: pdflatex (file ./Carlito-Bold.pfb): glyph `index130' undefined
1073       // warning  (pdf backend): unreferenced destination with name 'sth with glossary' 
1074       + "pdfTeX warning( \\((\\d|\\w)+\\))?: |"
1075       + "warning  \\(file .+\\) \\(pdf inclusion\\): PDF inclusion: |" // found PDF version TBD: rework for longer lines 
1076       + "\\* fontspec warning: |"
1077       + "Non-PDF special ignored!|"
1078       + "Missing character: There is no .* in font .*!$|"
1079       + "A space is missing\\. (No warning)\\.)")
1080   private String patternWarnLatex = "^(LaTeX Warning: |"
1081       + "LaTeX Font Warning: |"
1082       + "(Package|Class) .+ Warning: |"
1083       + "pdfTeX warning( \\((\\d|\\w)+\\))?: |" + "\\* fontspec warning: |"
1084       + "warning  \\(file .+\\) \\(pdf inclusion\\): PDF inclusion: |" // found PDF version TBD: rework for longer lines 
1085       + "\\* fontspec warning: |"
1086       + "Non-PDF special ignored!|"
1087       + "Missing character: There is no .* in font .*!$|"
1088       + "A space is missing\\. (No warning)\\.)";
1089 
1090   /**
1091    * Whether debugging of overfull/underfull hboxes/vboxes is on: 
1092    * If so, a bad box occurs in the last LaTeX run, a warning is displayed. 
1093    * For details, set $cleanUp to false, 
1094    * rerun LaTeX and have a look at the log-file. 
1095    * The default value is <code>true</code>. 
1096    */
1097   @RuntimeParameter
1098   @Parameter(name = "debugBadBoxes", defaultValue = "true")
1099   private boolean debugBadBoxes = true;
1100 
1101   /**
1102    * Whether debugging of warnings is on: 
1103    * If so, a warning in the last LaTeX run is displayed. 
1104    * For details, set $cleanUp to false, 
1105    * rerun LaTeX and have a look at the log-file. 
1106    * The default value is <code>true</code>. 
1107    */
1108   @RuntimeParameter
1109   @Parameter(name = "debugWarnings", defaultValue = "true")
1110   private boolean debugWarnings = true;
1111 
1112   /**
1113    * Whether creation of pdf-files from latex-files goes via dvi-files. 
1114    * <p>
1115    * If <code>pdfViaDvi</code> is set 
1116    * and the latex processor needs repetitions, 
1117    * these are all done creating dvi 
1118    * and then pdf is created in a final step 
1119    * invoking the command {@link #dvi2pdfCommand}. 
1120    * If <code>pdfViaDvi</code> is not set, 
1121    * latex is directly converted into pdf. 
1122    * <p>
1123    * Currently, not only conversion of latex-files is affected, 
1124    * but also conversion of graphic files 
1125    * into graphic formats which allow inclusion in the tex-file. 
1126    * If it goes via latex, 
1127    * then the formats are more based on (encapsulated) postscript; 
1128    * else on pdf. 
1129    * <p>
1130    * In the dvi-file for jpg, png and svg 
1131    * only some space is visible and only in the final step 
1132    * performed by {@link #dvi2pdfCommand}, 
1133    * the pictures are included using the bounding boxes 
1134    * given by the .bb or the .xbb-file. 
1135    * These are both created by $ebbCommand. 
1136    * <p>
1137    * Of course, the target dvi is not affected: 
1138    * This uses always the dvi-format. 
1139    * What is also affected are the tasks 
1140    * creating html, odt or docs: 
1141    * Although these are based on htlatex which is always dvi-based, 
1142    * the preprocessing is done in dvi or in pdf. 
1143    * Also the task txt is affected. 
1144    * <p>
1145    * As indicated in {@link #latex2pdfCommand}, 
1146    * the processor <code>xelatex</code> does not create <code>dvi</code> 
1147    * but <code>xdv</code> files. 
1148    * In a sense, the <code>xdv</code> format is an extension of <code>dvi</code>} 
1149    * but as for the <code>xdv</code> format there is no viewer, 
1150    * no way <code>htlatex</code> or other applications 
1151    * (except the \xelatex-internal <code>xdvidpfmx<code>) 
1152    * and also no according mime type, 
1153    * we refrained from subsumming this under ``kind of dvi''. 
1154    * Thus, with <code>xelatex<code> the flag {@link #pdfViaDvi} may not be set. 
1155    * <p>
1156    * The default value is <code>false</code>. 
1157    */
1158   // if false: directly 
1159   @RuntimeParameter
1160   @Parameter(name = "pdfViaDvi", defaultValue = "false")
1161   private boolean pdfViaDvi = false;
1162 
1163   /**
1164    * The driver to convert dvi into pdf-files. 
1165    * Note that this must fit the options 
1166    * of the packages <code>xcolor</code>, <code>graphicx</code> 
1167    * and, provided no autodetection, <code>hyperref</code>. 
1168    * Sensible values are 
1169    * <code>dvipdf</code>, <code>dvipdfm</code>, <code>dvipdfmx</code>, 
1170    * and <code>dvipdft</code> 
1171    * (which is <code>dvipdfm</code> with option <code>-t</code>). 
1172    * Note that <code>dvipdf</code> is just a script 
1173    * around <code>dvips</code> using <code>gs</code> 
1174    * but does not provide proper options; so not allowed. 
1175    * The default value is <code>dvipdfmx</code>. 
1176    */
1177   @RuntimeParameter
1178   @Parameter(name = "dvi2pdfCommand", defaultValue = "dvipdfmx")
1179   private String dvi2pdfCommand = "dvipdfmx";
1180 
1181   /**
1182    * The options for the command {@link #dvi2pdfCommand}. 
1183    * The default value is <code>-V1.7<code> specifying the pdf version to be created. 
1184    * The default version for pdf format for {@link #dvi2pdfCommand} is version 1.5. 
1185    * The reason for using version 1.7 is <code>fig2dev</code> 
1186    * which creates pdf figures in version 1.7 
1187    * and forces {@link #latex2pdfCommand} in dvi mode to include pdf version 1.7 
1188    * and finally {@link #dvi2pdfCommand} to use that also to avoid warnings. 
1189    * <p>
1190    * Using {@link #latex2pdfCommand} if used to create pdf directly, 
1191    * by default also pdf version 1.5 is created. 
1192    * For sake of uniformity, it is advisable to create pdf version 1.7 also. 
1193    * In future this will be done uniformly through <code>\DocumentMetadata</code> command. 
1194    * The default value is <code>-V1.7</code> but will in future be the empty string again. 
1195    */
1196   @RuntimeParameter
1197   @Parameter(name = "dvi2pdfOptions", defaultValue = "")
1198   private String dvi2pdfOptions = "-V1.7";
1199 
1200   /**
1201    * The pattern is applied line by line to the log-file 
1202    * and matching triggers rerunning {@link #latex2pdfCommand} 
1203    * if {@link #maxNumReRunsLatex} is not yet reached 
1204    * to ensure termination. 
1205    * <p>
1206    * This pattern may never be ensured to be complete, 
1207    * because any package 
1208    * may indicate the need to rerun {@link #latex2pdfCommand} 
1209    * with its own pattern any new package may break completeness. 
1210    * Nevertheless, the default value aims completeness 
1211    * while be tight enough not to trigger a superfluous rerun. 
1212    * <p>
1213    * If the current default value is not appropriate, 
1214    * please overwrite it in the configuration 
1215    * and notify the developer of this plugin of the deficiency. 
1216    * The default value is given below. 
1217    */
1218   // FIXME: default? to be replaced by an array of strings? **** 
1219   // FIXME: explicit tests required for each pattern. 
1220   // Not only those but all patterns. 
1221   // FIXME: seems a problem with the pattern spreading over two lines 
1222   @RuntimeParameter
1223   @Parameter(name = "patternReRunLatex", defaultValue =
1224   // general message 
1225   "^(LaTeX Warning: Label\\(s\\) may have changed\\. "
1226       + "Rerun to get cross-references right\\.$|" +
1227       // default message in one line for packages 
1228       "Package \\w+ Warning: .*Rerun( .*|\\.)$|" +
1229       // works for 
1230       // Package totcount Warning: Rerun to get correct total counts
1231       // Package longtable Warning: Table widths have changed. Rerun LaTeX ...
1232       // Package hyperref Warning: Rerun to get outlines right (old hyperref)
1233       // Package rerunfilecheck Warning: File `...' has changed. Rerun.
1234       // ... 
1235       // default message in two lines for packages 
1236       // FIXME: would require parsing of more than one line 
1237       "Package rerunfilecheck Info: Checksums for |" +
1238       "Package \\w+ Warning: .*$" + "^\\(\\w+\\) .*Rerun( .*|\\.)$|" +
1239       // works for 
1240       // Package natbib Warning: Citation\\(s\\) may have changed.
1241       // (natbib)                Rerun to get citations correct.
1242       // Package Changebar Warning: Changebar info has changed.
1243       // (Changebar)                Rerun to get the bars right
1244       // Package rerunfilecheck Warning: File `foo.out' has changed.
1245       // (rerunfilecheck)                Rerun to get outlines right"
1246       // (rerunfilecheck)                or use package `bookmark'.
1247       // but not for 
1248       // Package biblatex Warning: Please (re)run Biber on the file:
1249       // (biblatex)                test
1250       // (biblatex)                and rerun LaTeX afterwards. 
1251       //
1252       // messages specific to various packages 
1253       "LaTeX Warning: Etaremune labels have changed\\.$|" +
1254       // 'Rerun to get them right.' is on the next line
1255       //
1256       // from package rerunfilecheck used by other packages like new hyperref 
1257       // Package rerunfilecheck Warning: File `foo.out' has changed.
1258       "\\(rerunfilecheck\\)                Rerun to get outlines right$|" +
1259       // Rerun LaTeX/makeindex to get index right 
1260       // Rerun LaTeX/makeindex to get glossary right (not makeglossary) 
1261       "\\(rerunfilecheck\\)                Rerun LaTeX)"
1262   //  (rerunfilecheck)                or use package `bookmark'.
1263   )
1264   private String patternReRunLatex =
1265       // general message 
1266       "^(LaTeX Warning: Label\\(s\\) may have changed\\. "
1267           + "Rerun to get cross-references right\\.$|" +
1268           // default message in one line for packages 
1269           "Package \\w+ Warning: .*Rerun( .*|\\.)$|" +
1270           // works for 
1271           // Package totcount Warning: Rerun to get correct total counts
1272           // Package longtable Warning: Table widths have changed. Rerun LaTeX ...
1273           // Package hyperref Warning: Rerun to get outlines right (old hyperref)
1274           // ... 
1275           // default message in two lines for packages 
1276           "Package rerunfilecheck Info: Checksums for |" +
1277           "Package \\w+ Warning: .*$" + "^\\(\\w+\\) .*Rerun( .*|\\.)$|" +
1278           // works for 
1279           // Package natbib Warning: Citation\\(s\\) may have changed.
1280           // (natbib)                Rerun to get citations correct.
1281           // Package Changebar Warning: Changebar info has changed.
1282           // (Changebar)                Rerun to get the bars right
1283           //
1284           // messages specific to various packages 
1285           "LaTeX Warning: Etaremune labels have changed\\.$|" +
1286           // 'Rerun to get them right.' is on the next line
1287           //
1288           // from package rerunfilecheck used by other packages like new hyperref 
1289           // Package rerunfilecheck Warning: File `foo.out' has changed.
1290           "\\(rerunfilecheck\\)                Rerun to get outlines right$|" +
1291           // Rerun LaTeX/makeindex to get index right
1292           // Rerun LaTeX/makeindex to get glossary right (not makeglossary)
1293           "\\(rerunfilecheck\\)                Rerun LaTeX)";
1294   // (rerunfilecheck)                or use package `xxx'.
1295 
1296   /**
1297    * The maximal allowed number of reruns of {@link #latex2pdfCommand}. 
1298    * This is to avoid endless repetitions. 
1299    * The default value is 5. 
1300    * This shall be non-negative 
1301    * or <code>-1</code> which signifies that there is no threshold. 
1302    */
1303   @RuntimeParameter
1304   @Parameter(name = "maxNumReRunsLatex", defaultValue = "5")
1305   private int maxNumReRunsLatex = 5;
1306 
1307   // parameters for bibliography 
1308 
1309   /**
1310    * The BibTeX command to create a bbl-file 
1311    * from an aux-file and a bib-file 
1312    * (using a bst-style file). 
1313    * The default value is <code>bibtex</code>. 
1314    */
1315   @RuntimeParameter
1316   @Parameter(name = "bibtexCommand", defaultValue = "bibtex")
1317   private String bibtexCommand = "bibtex";
1318 
1319   // FIXME: Any parameters for bibtex? 
1320   // Usage: bibtex [OPTION]... AUXFILE[.aux]
1321   //   Write bibliography for entries in AUXFILE to AUXFILE.bbl,
1322   //   along with a log file AUXFILE.blg.
1323   // -min-crossrefs=NUMBER  include item after NUMBER cross-refs; default 2
1324   // -terse                 do not print progress reports
1325   // -help                  display this help and exit
1326   // -version               output version information and exit
1327 
1328   // how to detect errors/warnings??? 
1329   //Process exited with error(s)
1330 
1331   /**
1332    * The options for the command {@link #bibtexCommand}. 
1333    * The default value is the empty string. 
1334    */
1335   @RuntimeParameter
1336   @Parameter(name = "bibtexOptions", defaultValue = "")
1337   private String bibtexOptions = "";
1338 
1339   /**
1340    * The Pattern in the blg-file 
1341    * indicating that {@link #bibtexCommand} failed. 
1342    * The default value is chosen 
1343    * according to the <code>bibtex</code> documentation. 
1344    */
1345   @RuntimeParameter
1346   @Parameter(name = "patternErrBibtex", defaultValue = "error message")
1347   private String patternErrBibtex = "error message";
1348 
1349   /**
1350    * The Pattern in the blg-file 
1351    * indicating a warning {@link #bibtexCommand} emitted. 
1352    * The default value is chosen 
1353    * according to the <code>bibtex</code> documentation. 
1354    */
1355   @RuntimeParameter
1356   @Parameter(name = "patternWarnBibtex", defaultValue = "^Warning--")
1357   private String patternWarnBibtex = "^Warning--";
1358 
1359   // parameters for index 
1360 
1361   /**
1362    * The shape of the lines of an IDX file
1363    * with explicit identifier of the index. 
1364    * These lines are caused by commands <code>\sindex</code>, 
1365    * whereas the lines without index name 
1366    * come from commands <code>\index</code>. 
1367    * Presence of that pattern identifies multi-index 
1368    * to be treated by {@link Converter#Splitindex}, 
1369    * absence indicates a single index 
1370    * to be treated by {@link Converter#Makeindex}. 
1371    * Note that this regular expression has three groups
1372    * as in the specification of <code>splitindex</code>. 
1373    * <p>
1374    * The middle one has index {@link LatexProcessor#GRP_IDX_IDENT} 
1375    * and the value <code>yyy</code> identifies the index to be created. 
1376    * In particular, 
1377    * {@link Converter#Splitindex} creates an index file <code>xxx-yy.idx</code> 
1378    * If lines with and without explicit index identifier occur, 
1379    * the name of the index not explititly given is just <code>idx</code>. 
1380    * The first and the last group together form the entries of the index files 
1381    * code>xxx-yy.idx</code>. 
1382    * <p>
1383    * Note that the default value applies to the Perl version of <code>splitindex</code> 
1384    * and applies also to the internal workings of this java code 
1385    * and to the configuration file of <code>latexmk</code>. 
1386    * Although <code>splitindex</code> is also available as a lua file, 
1387    * this requires slightly different default pattern 
1388    * which is not compatible with what is needed at the other places. 
1389    */
1390   @RuntimeParameter
1391   @Parameter(name = "patternMultiIndex",
1392     defaultValue = "^(\\\\indexentry)\\[([^]]*)\\](.*)$")
1393   private String patternMultiIndex = "^(\\\\indexentry)\\[([^]]*)\\](.*)$";
1394 
1395   /**
1396    * The MakeIndex command to create an ind-file 
1397    * from an idx-file logging on an ilg-file. 
1398    * The default value is <code>makeindex</code>. 
1399    */
1400   @RuntimeParameter
1401   @Parameter(name = "makeIndexCommand", defaultValue = "makeindex")
1402   private String makeIndexCommand = "makeindex";
1403 
1404   /**
1405    * The options for the command {@link #makeIndexCommand}. 
1406    * Note that the option <code>-o xxx.ind</code> to specify the output file 
1407    * is not allowed because this plugin 
1408    * expects the output for the latex main file <code>xxx.tex</code> 
1409    * <code>xxx.ind</code>. 
1410    * Likewise, the option <code>-t xxx.ilg</code> 
1411    * to specify the logging file is not allowed, 
1412    * because this software uses the standard logging file 
1413    * to detect failures processing the idx-file. 
1414    * Also the option <code>-i</code> 
1415    * which specifies reading the raw index from standard input 
1416    * is not allowed. 
1417    * Specifying a style file with option <code>-s yyy.ist</code> 
1418    * is possible if only an index is used but no glossary. 
1419    * FIXME: rethink what about multiple indices. 
1420    * <p>
1421    * Note that the options specified here 
1422    * are also used to create glossaries. 
1423    * In addition for glossaries, the options 
1424    * <code>-s</code>, <code>-o</code> and <code>-t</code> are used. 
1425    * Thus also these options should not be used. 
1426    * The default value is the empty string. 
1427    * Useful options in this context are 
1428    * <ul>
1429    * <li><code>-c</code> remove blanks from index entries 
1430    * <li><code>-g</code> german ordering
1431    * <li><code>-l</code> letter ordering
1432    * <li><code>-r</code> without collecting index entries 
1433    * on 3 or more successive pages. 
1434    * </ul>
1435    */
1436   @RuntimeParameter
1437   @Parameter(name = "makeIndexOptions", defaultValue = "")
1438   private String makeIndexOptions = "";
1439 
1440   /**
1441    * The Pattern in the ilg-file 
1442    * indicating that {@link #makeIndexCommand} failed. 
1443    * The default value <code>(!! Input index error )</code> 
1444    * is chosen according to the <code>makeindex</code> documentation. 
1445    * 
1446    * The pattern is applied line-wise to the log file of the {@link #makeIndexCommand} 
1447    * and matching indicates that {@link #makeIndexCommand} failed with an error. 
1448    * Note that {@link #makeIndexCommand} is invoked either directly, 
1449    * via {@link #splitIndexCommand} or via {@link #makeGlossariesCommand}. 
1450    * In the first two cases, the log file is an ilg-file. 
1451    * For the last case, not the actual value for {@link #makeIndexCommand} is used 
1452    * but the default value. 
1453    * 
1454    * The default value for the pattern <code>(!! Input index error )</code> 
1455    * is chosen according to the <code>makeindex</code> documentation. 
1456    */
1457   @RuntimeParameter
1458   @Parameter(name = "patternErrMakeIndex",
1459       defaultValue = "(!! Input index error )")
1460   private String patternErrMakeIndex = "(!! Input index error )";
1461 
1462   /**
1463    * The Pattern in the ilg-file 
1464    * indicating a warning {@link #makeIndexCommand} emitted. 
1465    * The default value <code>(## Warning )</code> 
1466    * is chosen according to the <code>makeindex</code> documentation. 
1467    */
1468   @RuntimeParameter
1469   @Parameter(name = "patternWarnMakeIndex", defaultValue = "(## Warning )")
1470   private String patternWarnMakeIndex = "(## Warning )";
1471 
1472   /**
1473    * The SplitIndex command to create ind-files 
1474    * from an idx-file logging on ilg-files. 
1475    * This command invokes {@link #makeIndexCommand}. 
1476    * The default value is <code>splitindex</code>. 
1477    */
1478   @RuntimeParameter
1479   @Parameter(name = "splitIndexCommand", defaultValue = "splitindex")
1480   private String splitIndexCommand = "splitindex";
1481 
1482   /**
1483    * The options for {@link #splitIndexCommand}. 
1484    * Here, one has to distinguish between the options 
1485    * processed by {@link #splitIndexCommand} 
1486    * and those passed to {@link #makeIndexCommand}. 
1487    * The second category cannot be specified here, 
1488    * it is already given by {@link #makeIndexOptions}. 
1489    * In the first category is the option <code>-m</code> 
1490    * to specify the {@link #makeIndexCommand}. 
1491    * This is used automatically and cannot be specified here. 
1492    * Since {@link #splitIndexCommand} is used 
1493    * in conjunction with package <code>splitidx</code>, 
1494    * which hardcodes various parameters 
1495    * which are the default values for {@link #splitIndexCommand} 
1496    * and because the option may not alter certain interfaces, 
1497    * the only option which may be given explicitly 
1498    * is <code>-V</code>, the short cut for <code>--verbose</code>. 
1499    * Do not use <code>--verbose</code> either for sake of portability. 
1500    * The default value is <code>-V</code>; it could also be empty. 
1501    */
1502   @RuntimeParameter
1503   @Parameter(name = "splitIndexOptions", defaultValue = "-V")
1504   private String splitIndexOptions = "-V";
1505 
1506   // parameters for glossary 
1507 
1508   /**
1509    * The MakeGlossaries command to create a gls-file 
1510    * from a glo-file (invoked without file ending) 
1511    * also taking ist-file or xdy-file 
1512    * into account logging on a glg-file. 
1513    * The default value is <code>makeglossaries</code>. 
1514    */
1515   @RuntimeParameter
1516   @Parameter(name = "makeGlossariesCommand", defaultValue = "makeglossaries")
1517   private String makeGlossariesCommand = "makeglossaries";
1518 
1519   /**
1520    * The options for the command {@link #makeGlossariesCommand}. 
1521    * These are the options for <code>makeindex</code> 
1522    * (not for {@link #makeIndexCommand}) 
1523    * and for <code>xindy</code> (also hardcoded). 
1524    * The aux-file decides on whether program is executed 
1525    * and consequently which options are used. 
1526    * <p>
1527    * The default value is the empty option string. 
1528    * Nevertheless, <code>xindy</code> is invoked as 
1529    * <code>xindy -L english  -I xindy -M ...</code>. 
1530    * With option <code>-L german</code>, this is added. 
1531    * Options <code>-M</code> for <code>xindy</code> 
1532    * <code>-s</code> for <code>makeindex</code> and 
1533    * <code>-t</code> and <code>-o</code> for both, 
1534    * <code>xindy</code> and <code>makeindex</code>. 
1535    */
1536   @RuntimeParameter
1537   @Parameter(name = "makeGlossariesOptions", defaultValue = "")
1538   private String makeGlossariesOptions = "";  @RuntimeParameter
1539 
1540   /**
1541    * **This parameter is deprecated since version 2.1.** 
1542    * The pattern is applied line-wise to each log file of the index processor, 
1543    * invoked by {@link #makeGlossariesCommand} 
1544    * which is either <code>makeglossaries</code> or <code>xindy</code>. 
1545    * It is appended to the log file by <code>makeglossaries</code> in case the according index processor had an error. 
1546    * 
1547    * Note that from the point of view of a build tool, 
1548    * this is a redundant piece of information. 
1549    * It is only written to help an end-user to understand the error message of the index processor better. 
1550    * Also note that there is no according message for warnings of the index processor 
1551    * and that the above message is written by <code>makeglossaries</code> 
1552    * but not by <code>makeglossaries-lite</code>. 
1553    */
1554   @Parameter(name = "patternErrMakeGlossaries", defaultValue = "^makeglossaries diagnostic messages:$")
1555   private String patternErrMakeGlossaries = "^makeglossaries diagnostic messages:$";
1556 
1557   /**
1558    * The pattern in the glg-file 
1559    * indicating that running <code>xindy</code> 
1560    * via {@link #makeGlossariesCommand} failed. 
1561    * The default value is <code>(^ERROR: )</code> (note the space). 
1562    * If this is not appropriate, please modify 
1563    * and notify the developer of this plugin. 
1564    */
1565   // FIXME: This is not used. 
1566   @RuntimeParameter
1567   @Parameter(name = "patternErrXindy", defaultValue = "(^ERROR: )")
1568   private String patternErrXindy = "(^ERROR: )";
1569 
1570   /**
1571    * The pattern in the glg-file 
1572    * indicating a warning when running <code>xindy</code> 
1573    * via {@link #makeGlossariesCommand}. 
1574    * The default value is <code>(^WARNING: )</code> 
1575    * (note the space and the brackets). 
1576    * If this is not appropriate, please modify 
1577    * and notify the developer of this plugin. 
1578    */
1579   @RuntimeParameter
1580   @Parameter(name = "patternWarnXindy", defaultValue = "(^WARNING: )")
1581   private String patternWarnXindy = "(^WARNING: )";
1582 
1583 
1584   // parameters for pythontex
1585 
1586   /**
1587    * The Pythontex command which creates a folder <code>pythontex-files-xxx</code> 
1588    * given by {@link #prefixPytexOutFolder} 
1589    * with various files inside 
1590    * from a pytxcode-file (invoked without file ending) 
1591    * and logging in a plg-file. 
1592    * The default value is <code>pythontex</code> 
1593    * but as long as this does not write a log file this software really needs, 
1594    * we have to configure it with <code>pythontexW</code> 
1595    * which is a simple wrapper of <code>pythontex</code> writing a log file. 
1596    * CAUTION: Since <code>pythontexW</code> is not registered with this software, 
1597    * one has to specify it with its category as <code>pythontexW:pythontex</code>. 
1598    */
1599   @RuntimeParameter
1600   @Parameter(name = "pythontexCommand", defaultValue = "pythontex")
1601   private String pythontexCommand = "pythontex";
1602 
1603   /**
1604    * The options for the command {@link #pythontexCommand}. 
1605    * <p> 
1606    * For the possibilities see the manual of the pythontex package 
1607    * or the help dialog of <code>pythontex</code>. 
1608    * CAUTION: <code>--rerun</code> and <code>--runall</code> cannot be specified both in one invocation. 
1609    * In the context of this software, the option
1610    * <code>--interactive</code> is not appropriate. 
1611    * CAUTION: For many options of the command line tool, 
1612    * there is an according package option and the latter overrides the former. 
1613    * CAUTION: This software overwrites settings <code>--rerun</code> and <code>--runall</code> anyway, 
1614    * and forces setting <code>--rerun=always</code>. 
1615    * The default value is <code>--rerun=always</code>. 
1616    */
1617   @RuntimeParameter
1618   @Parameter(name = "pythontexOptions", defaultValue = "--rerun=always")
1619   private String pythontexOptions = "--rerun=always";
1620 
1621 
1622   /**
1623    * The pattern in the plg-file 
1624    * indicating that running <code>pythontex</code>, resp. <code>pythontexW</code> 
1625    * via {@link #pythontexCommand} failed. 
1626    * The default value is essentially 
1627    * <code>(PythonTeX:  .+ -|    - Current: ) [1-9][0-9]* error\\(s\\), [0-9]+ warning\\(s\\)</code> (note the spaces)
1628    * but due to a bug in <code>pythontex</code> it is slightly more complicated. 
1629    * If this is not appropriate, please modify 
1630    * and notify the developer of this plugin. 
1631    */
1632   @RuntimeParameter
1633   @Parameter(name = "patternErrPyTex",
1634       defaultValue = "\\* PythonTeX error|(PythonTeX:  .+ -|    - Current: ) [1-9][0-9]* error\\(s\\), [0-9]+ warning\\(s\\)")
1635   private String patternErrPyTex =
1636       "\\* PythonTeX error|(PythonTeX:  .+ -|    - Current: ) [1-9][0-9]* error\\(s\\), [0-9]+ warning\\(s\\)";
1637 
1638   /**
1639    * The pattern in the plg-file 
1640    * indicating a warning when running <code>pythontex</code>, resp. <code>pythontexW</code> 
1641    * via {@link #pythontexCommand}. 
1642    * The default value is <code>(PythonTeX:  .+ -|    - Current: ) [0-9]+ error\\(s\\), [1-9][0-9]* warning\\(s\\)</code> 
1643    * (note the space and the brackets). 
1644    * If this is not appropriate, please modify 
1645    * and notify the developer of this plugin. 
1646    */
1647   @RuntimeParameter
1648   @Parameter(name = "patternWarnPyTex",
1649       defaultValue = "(PythonTeX:  .+ -|    - Current: ) [0-9]+ error\\(s\\), [1-9][0-9]* warning\\(s\\)")
1650   private String patternWarnPyTex =
1651       "(PythonTeX:  .+ -|    - Current: ) [0-9]+ error\\(s\\), [1-9][0-9]* warning\\(s\\)";
1652 
1653   // This is readonly: neither the package nor the tool pythontex can change this. 
1654   // CAUTION: the default also occurs in parameter patternCreatedFromLatexMain
1655   /**
1656    * The prefix of the name of the folder written by {@link #pythontexCommand}. 
1657    * The full name of that folder is this prefix 
1658    * followed by the jobname of the latex main file, 
1659    * i.e. the filename without ending. 
1660    * 
1661    * CAUTION: This is readonly, 
1662    * because in both, the pythontex tool and the according latex package 
1663    * this prefix is hardcoded at time of this writing. 
1664    */
1665   @RuntimeParameter
1666   @Parameter(name = "pythontex-files-", defaultValue = "pythontex-files-",readonly = true)
1667   private String prefixPytexOutFolder = "pythontex-files-";
1668 
1669   /**
1670    * The Depythontex command invoked with no file ending 
1671    * to create a file <code>xxx.depytx.tex</code> file
1672    * from a tex-file, a depytx-file taking the output of <code>pythontex</code> into account 
1673    * and logging on a dplg-file. 
1674    * The default value is <code>depythontex</code> 
1675    * but as long as this does not write a log file this software really needs, 
1676    * we have to configure it with <code>depythontexW</code> 
1677    * which is a simple wrapper of <code>depythontex</code> writing a log file. 
1678    * CAUTION: Since <code>depythontexW</code> is not registered with this software, 
1679    * one has to specify it with its category as <code>depythontexW:depythontex</code>. 
1680    */
1681   @RuntimeParameter
1682   @Parameter(name = "depythontexCommand", defaultValue = "depythontex")
1683   private String depythontexCommand = "depythontex";
1684 
1685   /**
1686    * The additional options for the command {@link #depythontexCommand}. 
1687    * To run <code>depythontex</code> in the context of this software, 
1688    * the options <code>--overwrite --output file</code> are mandatory 
1689    * to create an output file at all and to overwrite if it already exists 
1690    * avoiding that <code>depythontex</code> enters interactive mode. 
1691    * Thus these options are added silently. 
1692    * This setting is the additional options. 
1693    * <p>
1694    * The default value is the empty option string. 
1695    * For the possibilites see the manual of the pythontex package 
1696    * or the help dialog of code>depythontex</code>. 
1697    */
1698   @RuntimeParameter
1699   @Parameter(name = "depythontexOptions", defaultValue = "")
1700   private String depythontexOptions = "";
1701 
1702   // parameters for latex2html-conversion 
1703 
1704   /**
1705    * The tex4ht command. 
1706    * Possible values are e.g. 
1707    * <code>htlatex</code> and <code>htxelatex</code>. 
1708    * The default value (for which this software is also tested) 
1709    * is <code>htlatex</code>. 
1710    */
1711   @RuntimeParameter
1712   @Parameter(name = "tex4htCommand", defaultValue = "htlatex")
1713   private String tex4htCommand = "htlatex";
1714 
1715   /**
1716    * The options for the <code>tex4ht</code>-style 
1717    * which creates a dvi-file or a pdf-file 
1718    * with information to create sgml, 
1719    * e.g. html or odt or something like that. 
1720    * The default value is <code>html,2</code>. 
1721    */
1722   @RuntimeParameter
1723   @Parameter(name = "tex4htStyOptions", defaultValue = "html,2")
1724   private String tex4htStyOptions = "html,2";
1725 
1726   /**
1727    * The options for <code>tex4ht</code> which extracts information 
1728    * from a dvi-file or from a pdf-file 
1729    * into the according lg-file and idv-file producing html-files 
1730    * and by need and if configured accordingly 
1731    * svg-files, 4ct-files and 4tc-files and a css-file and a tmp-file.
1732    * The former two are used by <code>t4ht</code> 
1733    * which is configured via {@link #t4htOptions}. 
1734    */
1735   @RuntimeParameter
1736   @Parameter(name = "tex4htOptions", defaultValue = "")
1737   private String tex4htOptions = "";
1738 
1739   /**
1740    * The options for <code>t4ht</code> which converts idv-file and lg-file 
1741    * into css-files, tmp-file and, 
1742    * by need and if configured accordingly into png files. 
1743    * The value <code>-p</code> prevents creation of png-pictures.
1744    * The default value is the empty string. 
1745    */
1746   @RuntimeParameter
1747   @Parameter(name = "t4htOptions", defaultValue = "")
1748   private String t4htOptions = "";
1749 
1750   /**
1751    * The pattern for the target files of goal {@link Target#html} 
1752    * for a given latex main file <code>xxx.tex</code>. 
1753    * The patterns for the other targets 
1754    * are hardcoded and take the form 
1755    * <code>^T$T\.yyy$</code>, where <code>yyy</code> 
1756    * may be an ending or an alternative of endings. 
1757    * <p>
1758    * For an explanation of the pattern <code>T$T</code>, 
1759    * see {@link #patternCreatedFromLatexMain}. 
1760    * Spaces and newlines are removed 
1761    * from that pattern before processing. 
1762    * <p>
1763    * The default value has the following components: 
1764    * <ul>
1765    * <li><code>^T$T\.x?html?$</code> 
1766    * is the main file. 
1767    * <li><code>^T$Tli\d+\.x?html?$</code> 
1768    * are lists: toc, lof, lot, indices, glossaries, NOT the bibliography. 
1769    * <li><code>^T$T(ch|se|su|ap)\d+\.x?html?$</code> 
1770    * are chapters, sections and subsections or below 
1771    * and appendices. 
1772    * <li><code>^T$T\d+\.x?html?$</code> 
1773    * are footnotes. 
1774    * <li><code>^T$T\.css$</code> 
1775    * are cascaded stylesheets. 
1776    * <li><code>^T$T-\d+\.svg$</code> and <code>^T$T\d+x\.png$</code>
1777    * are svg/png-files representing figures. 
1778    * <li><code>^(cmsy)\d+(-c)?-\d+c?\.png$</code> 
1779    * represents special symbols. 
1780    * </ul>
1781    * Note that the patterns for the html-files 
1782    * can be summarized as <code>^T$T((ch|se|su|ap|li)?\d+)?\.x?html?$</code>. 
1783    * Adding the patterns for the css-file and the svg-files, we obtain 
1784    * <pre>
1785    * ^T$T(((ch|se|su|ap|li)?\d+)?\.x?html?|
1786    * \.css|
1787    * \d+x\.x?bb|
1788    * \d+x\.png|
1789    * -\d+\.svg)$
1790    * </pre>. 
1791    * <p>
1792    * The pattern is designed to match quite exactly 
1793    * the files to be copied to {@link #targetSiteDirectory}, 
1794    * for the goal {@link Target#html}, 
1795    * not much more and at any case not less. 
1796    * since {@link #tex4htCommand} is not well documented, 
1797    * and still subject to development, 
1798    * this pattern cannot be guaranteed to be final. 
1799    * If the user finds an extension, (s)he is asked to contribute 
1800    * and to notify the developer of this plugin. 
1801    * Then the default value will be extended. 
1802    */
1803   @RuntimeParameter
1804   @Parameter(name = "patternT4htOutputFiles", defaultValue = "")
1805   private String patternT4htOutputFiles =
1806       "^(T$T(((ch|se|su|ap|li)?\\d+)?\\.x?html?|" +
1807       /*   */"\\.css|" +
1808       /*   */"\\d+x\\.x?bb|" +
1809       /*   */"\\d+x\\.png|" +
1810       /*   */"-\\d+\\.svg)|" + "(cmsy)\\d+(-c)?-\\d+c?\\.png)$";
1811 
1812   // parameters for further conversions 
1813 
1814   /**
1815    * The latex2rtf command to create rtf from latex directly. 
1816    * The default value is <code>latex2rtf</code>. 
1817    */
1818   @RuntimeParameter
1819   @Parameter(name = "latex2rtfCommand", defaultValue = "latex2rtf")
1820   private String latex2rtfCommand = "latex2rtf";
1821 
1822   /**
1823    * The options of the command {@link #latex2rtfCommand}. 
1824    * The default value is the empty string. 
1825    */
1826   @RuntimeParameter
1827   @Parameter(name = "latex2rtfOptions", defaultValue = "")
1828   private String latex2rtfOptions = "";
1829 
1830   /**
1831    * The odt2doc command 
1832    * to create MS word-formats from otd-files. 
1833    * The default value is <code>odt2doc</code>; 
1834    * equivalent here is <code>unoconv</code>. 
1835    * Note that <code>odt2doc</code> just calls <code>unoconv</code> 
1836    * with odt-files as input and doc-file as default output. 
1837    *
1838    * @see #odt2docOptions
1839    */
1840   @RuntimeParameter
1841   @Parameter(name = "odt2docCommand", defaultValue = "odt2doc")
1842   private String odt2docCommand = "odt2doc";
1843 
1844   /**
1845    * The options of the command {@link #odt2docCommand}. 
1846    * Above all specification of output format 
1847    * via the option <code>-f</code>. 
1848    * Invocation is <code>odt2doc -f&lt;format&gt; &lt;file&gt;.odt</code>. 
1849    * All output formats are shown by <code>odt2doc --show</code> 
1850    * but the formats interesting in this context 
1851    * are <code>doc, doc6, doc95,docbook, docx, docx7, ooxml, rtf</code>. 
1852    * Interesting also the verbosity options <code>-v, -vv, -vvv</code> 
1853    * the timeout <code>-T=secs</code> and <code>--preserve</code> 
1854    * to keep permissions and timestamp of the original document. 
1855    * The default value is <code>-fdocx</code>. 
1856    *
1857    * @see #odt2docCommand
1858    */
1859   @RuntimeParameter
1860   @Parameter(name = "odt2docOptions", defaultValue = "-fdocx")
1861   private String odt2docOptions = "-fdocx";
1862 
1863   /**
1864    * The pdf2txt-command for converting pdf-files into plain text files. 
1865    * The default value is <code>pdftotext</code>. 
1866    *
1867    * @see #pdf2txtOptions
1868    */
1869   @RuntimeParameter
1870   @Parameter(name = "pdf2txtCommand", defaultValue = "pdftotext")
1871   private String pdf2txtCommand = "pdftotext";
1872 
1873   /**
1874    * The options of the command {@link #pdf2txtCommand}. 
1875    * The default value is the empty string. 
1876    *
1877    * @see #pdf2txtCommand
1878    */
1879   // TBD: check 
1880   @RuntimeParameter
1881   @Parameter(name = "pdf2txtOptions", defaultValue = "-q")
1882   private String pdf2txtOptions = "-q";
1883 
1884 
1885 
1886   /**
1887    * The chktex-command for checking latex main files.
1888    * Note that the allowed return values are
1889    * <ul>
1890    * <li>1 if an error in execution occurs,
1891    * e.g. option -neee although -n requires a number.</li>
1892    * <li>3 if an error was found except if case 1 occurs.
1893    * Note that all findings are warnings
1894    * if not configured as errors with -exx, xx a number.</li>
1895    * <li>2 if a warning was found, except if one of the above cases occur.
1896    * one can deactivate always.</li>
1897    * <li>0 if neither of the above occurred.
1898    * Note that still warnings could be given but deactivated,
1899    * e.g. excluded linewise.</li>
1900    * </ul>
1901    * The default value is <code>chktex</code>.
1902    *
1903    * @see #chkTexOptions
1904    * @see CommandExecutor.ReturnCodeChecker#IsOne
1905    */
1906   @RuntimeParameter
1907   @Parameter(name = "chkTexCommand", defaultValue = "chktex")
1908   private String chkTexCommand = "chktex";
1909 
1910 
1911   /**
1912    * The options of the command {@link #chkTexCommand}, 
1913    * except <code>-o output-file</code> 
1914    * specifying the output file which is added automatically. 
1915    * <p>
1916    * Here is a list of options useful in this context. 
1917    * The first group of these are muting options: 
1918    * <ul>
1919    * <li><code>-w</code>, <code>-e</code>, <code>-m</code>, 
1920    * Make the message number passed as parameter 
1921    * a warning/an error/a message and turns it on. 
1922    * Messages are not counted. 
1923    * <li><code>-n</code>
1924    * Turns the warning/error number passed as a parameter off. 
1925    * <li><code>-L</code>
1926    * Turns off suppression of messages on a per line basis. 
1927    * </ul>
1928    * The next group of interesting options are for output control: 
1929    * <ul>
1930    * <li><code>-q</code>
1931    * Shuts up about copyright information.
1932    * <li><code>-o output-file</code>
1933    * Specifies the output file. This is added automatically 
1934    * and shall thus not be specified by the user. 
1935    * <li><code>-b[0|1]</code>
1936    * If you use the -o switch, and the named outputfile exists,
1937    * it will be renamed to <code>filename.bak</code>.
1938    * <li><code>-f format</code>
1939    * Specifies the format of the output 
1940    * via a format similar to <code>printf()</code>. 
1941    * For details consult the manual. 
1942    * <li><code>-vd</code>
1943    * Verbosity level followed by a number <code>d</code> 
1944    * specifying the format of the output. 
1945    * The verbosity number is resolved as a pattern 
1946    * as if given by the option <code>-f format</code>. 
1947    * Thus the option <code>-v</code> is ignored 
1948    * if the option <code>-f format</code> is specified. 
1949    * </ul>
1950    * The default value is <code>-q -b0</code> 
1951    * avoiding verbose output and backing up the output log-file. 
1952    *
1953    * @see #chkTexCommand
1954    */
1955   // -v: verbosity: 
1956   //     - 0 File:Line:Column:Warning number:Warning message
1957   //         No specification on the kind of the entry 
1958   //     - 1 1st line: (Error|Warning|Message) in <File> line <Line>: message 
1959   //         2nd line: according line of the source 
1960   //         3rd line: cursor ^ pointing to the place where the problem is 
1961   //     - 2 1st line as for level 1 
1962   //         2nd line: line of source with pointer for the problem 
1963   //                   has shape:  
1964   //     - 3 "File", line Line: Warning message 
1965   //     - 4 1st line as for 3, 
1966   //         2nd line as for 1 
1967   //         3rd line as for 1 
1968   // -f format: this allows to create more flexible formats as with -vxxx 
1969   //         to determine the kind of entry (Error|Warning|Message) 
1970   //         if kind is given, it must be at the beginning of the line 
1971   // -q: no copyright information 
1972   // -b: toggle creation of backup file: with -o: yes, additional -b: no 
1973   //     explicitly as -b0 and -b1, respectively. 
1974   @RuntimeParameter
1975   @Parameter(name = "chkTexOptions", defaultValue = "-q -b0")
1976   private String chkTexOptions = "-q -b0";
1977 
1978   /**
1979    * The diff-command for diffing pdf-files strictly or just visually 
1980    * to check that the created pdf files are equivalent with prescribed ones. 
1981    * CAUTION: there are two philisophies: 
1982    * Either the latex source files are created in a way that they reproduce strictly. 
1983    * Then a strict diff command like <code>diff</code> is appropriate. 
1984    * Else another diff command is required which checks for a kind of visual equality. 
1985    * The default value is a mere <code>diff</code>. 
1986    * Alternatives are <code>diff-pdf</code> and <code>diff-pdf-visually</code> 
1987    * both implementing a visual diff. 
1988    * Note that unlike for other tools, no options can be passed in this case explicitly. 
1989    * CAUTION: Expected return value 0 means same, 1 normal difference, all other values: failure. 
1990    * Thus <code>diff-pdf-visually</code> is not allowed, 
1991    * because uses different return code: exchanging 1 and 2. 
1992    * Thus usable for a wrapper only. 
1993    * TBD: work into this addition. 
1994    */
1995   @RuntimeParameter
1996   @Parameter(name = "diffPdfCommand", defaultValue = "diff")
1997   private String diffPdfCommand = "diff";
1998 
1999   // an alternative would be exiftool. 
2000   // The naive output turns out to be very much misleading: 
2001   // exiftool xxx.pdf 
2002   // has output reminding of pdfinfo xxx.pdf 
2003   // but the existence of many dates and slight differences in the names of the tags should warn us. 
2004   // We shall use instead: 
2005   // exiftool -X xxx.pdf 
2006   // which yields an xml representation. 
2007   // The advantage of this is, that tags are endowed with namespaces and can thus be easily distinguished. 
2008   // For example we have PDF:CreateDate and XMP-xmp:CreateDate
2009   // The technique to identify pieces of information with those by pdfinfo 
2010   // is by modifying: 
2011   // exiftool -PDF:CreateDate=2020-01-01T00:01:02Z xxx.pdf 
2012   // and reading in pdfinfo -rawdates xxx.pdf to see what is really written: it is CreationDate. 
2013   // Similarly we find out, that 
2014   // exiftool -PDF:ModifyDate=2020-02-28T00:01:02Z xxx.pdf 
2015   // affects ModDate: strange, not the same key. 
2016   //
2017   // Strange, these are not the dates displayed by 
2018   // exiftool xxx.pdf
2019   // because they are unchanged. 
2020   // This is misleading as they have similar keys. 
2021   // 
2022   // exiftool performs changes as an incremental update, 
2023   // i.e. the old versions are not eliminated, but hidden by the new entries. 
2024   // An update affects also all entries which depend on the one explicitly changed. 
2025   // This is important to know, 
2026   // because changing CreationDate after compilation is not the same as direct compilation with that timestamp. 
2027   // The original values can be recovered. 
2028   // exiftool -PDF-update:All= manualLMP.pdf
2029   // To make this permanent, use linearization (use qpdf not exiftool): 
2030   //   #!/usr/bin/env bash
2031   // # Strip metadata and re-linearise:
2032   // exiftool -all= -overwrite_original "$1"
2033   // mv "$1" /tmp/temp.pdf
2034   // qpdf --linearize /tmp/temp.pdf "$1"
2035 
2036 
2037   // Well, then no option is required but result is not strict ISO 8601 but maybe works anyway
2038   // but one has to make the keys configurable, because they depend on the tool 
2039   // On the other hand, PDF specification 2.0 expands also on keys and deprecation 
2040   // | tool     | exiftool -X    | pdfinfo -meta  | pdfinfo         | PDF2.0 spec    | location | 
2041   // | -------- | -------------- | -------------- | --------------- | -------------- | -------- |
2042   // |          | PDF:Title      |                | Title           | Title          | 14.3.3   |
2043   // |          | PDF:Author     |                | Author          | Author         | 14.3.3   |
2044   // |          | PDF:Subject    |                | Subject         | Subject        | 14.3.3   |
2045   // |          | PDF:Keywords   |                | Keywords        | Keywords       | 14.3.3   |
2046   // |          | PDF:Creator    |                | Creator         | Creator        | 14.3.3   |
2047   // |          | PDF:Producer   | pdf:Producer   | Producer        | Producer       | 14.3.3   |
2048   // |          | PDF:CreateDate |                | CreationDate    | CreationDate   | 14.3.3   |
2049   // |          | PDF:ModifyDate |                | ModDate         | ModDate        | 14.3.3   |
2050   // |          | ?              |                | ?               | Trapped        | 14.3.3   |
2051   // |          | ?              |                | ?               | Marked         | 14.7.1   |
2052   // |          | ---            |                | UserProperties  | UserProperties | 14.7.1   |
2053   // |          | ---            |                | Suspects        | Suspects       | 14.7.1   |
2054   // |          | File Size      |                | File size       |
2055   // |          | MIME Type      |                |
2056   // |          | PDF:PDFVersion | pdf:PDFVersion | PDF version     |
2057   // |          | PDF:Linearized |                | ---             |
2058   // |          | PDF:PageMode   |                | ---             |
2059   // |          | ---            |                | Custom Metadata |
2060   // |          | ---            |                | Metadata Stream |
2061   // |          | ---            |                | Tagged          |
2062 
2063   // |          | ---            |                | Form            |
2064   // |          | ---            |                | JavaScript      | JavaScript     |  7.7.4 |
2065   // |          | PDF:PageCount  |                | Pages           | Pages          |  7.7.4 |
2066   // |          | PDF:Language 
2067   // |          | ---            |                | Encrypted       |
2068   // |          | ---            |                | Page size       |
2069   // |          | ---            |                | Page rot        |
2070   // |          | ---            |                | Optimized       | not mentioned |---|
2071   //
2072   // Also form differs: 
2073   // | tool     | key-value line                                         |
2074   // | -------- | ------------------------------------------------------ |
2075   // | exiftool | Modify Date                     : 2024:06:22 13:00:54Z |
2076   // | pdfinfo  | ModDate:         2024-06-22T13:00:54Z                  |
2077   // also observed in Keywords: , with blank vs ; without blanks 
2078   // File sise in bytes or in kb
2079   // The keys may vary, the location of the colon and also the value is not completely standardized. 
2080 
2081   // Strange with exiftool: 
2082   // $ exiftool -CreateDate manualLMP.pdf % yields
2083   // Create Date                     : 2024:06:30 21:11:54Z
2084   // so on the one hand, one can access any metadata with the internal name, 
2085   // but the return key may be different from the access key 
2086   // like 'Create Date' differs from 'CreateDate'. 
2087   // If it is only about blanks, then one could filter eliminating all blanks. 
2088   // not only leading and trailing ones. 
2089   // But as seen above, there are more complicated cases like ModDate 
2090   // so an explicit mapping is needed. 
2091   // exiftool -S and -S are without blanks in the key 
2092   // 
2093   // This can be changed: 
2094   //  $ exiftool -T -CreateDate manualLMP.pdf %yields 
2095   // 2024:06:30 21:11:54Z
2096   // without (wrong) key 
2097   // $ exiftool -X -CreateDate manualLMP.pdf  %yields 
2098   // <?xml version='1.0' encoding='UTF-8'?>
2099   // <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
2100 
2101   // <rdf:Description rdf:about='manualLMP.pdf'
2102   //   xmlns:et='http://ns.exiftool.org/1.0/' et:toolkit='Image::ExifTool 12.87'
2103   //   xmlns:PDF='http://ns.exiftool.org/PDF/PDF/1.0/'>
2104   //  <PDF:CreateDate>2024:06:30 21:11:54Z</PDF:CreateDate>
2105   // </rdf:Description>
2106   // </rdf:RDF>
2107   // This is a bit lengthy, but the key is correct. 
2108   //
2109   // Also ISO 6801 can be realized almost: 
2110   // $ exiftool -d %Y-%m-%dT%H:%M:%S%z -T -CreateDate manualLMP.pdf % yields 
2111   // 2024-06-30T21:11:54+0000
2112   // This is sensible, except for UTC where we want Z. 
2113   // The problem is that -0000 is equivalent also, 
2114   // but what we need is really canonical forms 
2115   // so that string equality is really time/timezone equality. 
2116   // $ exiftool -CreateDate -s -iso manualLMP.pdf % yields 
2117   // CreateDate                      : 2024:06:30 21:11:54Z
2118 
2119   // To override creation date: 
2120   // exiftool -CreateDate=2000-01-01T00:00:00Z manualLMP.pdf
2121   // but this is only an incremental update overwriting the original date 
2122   // undoing this is by 
2123   // exiftool -PDF-update:All= manualLMP.pdf
2124   // To make this permanent, use linearization (use qpdf not exiftool): 
2125 //   #!/usr/bin/env bash
2126 // # Strip metadata and re-linearise:
2127 // exiftool -all= -overwrite_original "$1"
2128 // mv "$1" /tmp/temp.pdf
2129 // qpdf --linearize /tmp/temp.pdf "$1"
2130 
2131 // only changing creation date of the original pdf allows to create a new pdf with given creation time. 
2132 // THis is not equivalent with the original anyway, 
2133 // for various reasons, e.g. ModDate is not changed as well also trailder ID. 
2134 // Another reason: incremental, reversible change, 
2135 // which is not what is done by latex compilers. 
2136   
2137 
2138 
2139 
2140 
2141 
2142 
2143 
2144   // TBD: eliminated hard coded keys and that like. 
2145   // exiftool is based on a perl lib, both tools are cross platform 
2146   // pdfinfo is in poppler and thus in texlive, so cross plattform 
2147   // 
2148   // To get ISO 8601 format, use 
2149   // exiftool -dateformat %Y-%m-%dT%H:%M:%S%z xxx.pdf
2150   // pdfinfo -isodates xxx.pdf is almost equivalent. 
2151   // Uses Z for utc whereas exiftool uses +0000 
2152   // also number of digits of timezone varies. 
2153   // Note that the keys differ, 
2154   // which prevents the author from supporting both, pdfinfo and exiftool. 
2155   // I think, there are canonical keys, namely these specified by the PDF format. 
2156   // To be maximally flexible, one can use a mapping 
2157   // from the tool specific keys to those specified for pdf. 
2158   // This software has to convert to epoch time, 
2159   // to write into SOURCE_DATE_EPOCH. 
2160   // exiftool can do this at once: exiftool -dateformat %s xxx.pdf
2161 
2162   /**
2163    * Command to retrieve metainfo from PDF files. 
2164    * Essentially, there are two possibilities, 
2165    * <code>exiftool</code> or <code>pdfinfo</code> 
2166    * but currently this software is restricted to the latter. 
2167    * At time of this writing, only creation time is considered. 
2168    * Note that meta info CreationTime is not identical 
2169    * with creation time in a file system. 
2170    * 
2171    * The default value is <code>pdfinfo</code>. 
2172    */
2173   @RuntimeParameter
2174   @Parameter(name = "pdfMetainfoCommand", defaultValue = "pdfinfo")
2175   private String pdfMetainfoCommand = "pdfinfo";
2176 
2177   // although rawdates are stored as defined in {Pdf20}, Section~7.9.4, 
2178   // we request isodates according to ISO 8601 
2179   // for further processing and better human-readability. 
2180   // The function relies on rawdates 
2181   // because one and the same date has a unique representation. 
2182   // doing without may work as well, but not so sure 
2183 
2184   /**
2185    * The general options for the command {@link #pdfMetainfoCommand} 
2186    * which is currently always <code>pdfinfo</code>. 
2187    * At time of this writing, there is one further kind of options, 
2188    * those for XMP metadata given by {@link #pdfMetainfoXmpOptions}. 
2189    * These refer to the same command but in different situations. 
2190    * <p>
2191    * For general options, at time of this writing, only creation time is considered. 
2192    * This software has little flexibility in treating various time formats, 
2193    * so it must be decided. 
2194    * Format offered by <code>pdfinfo</code> 
2195    * most commonly known and easily converted to the required epoch time, 
2196    * is really according to ISO 8601. 
2197    * This motivates <code>-isodates</code> to be a mandatory option. 
2198    * Further options do not make sense, 
2199    * as currently only creation time is used. 
2200    * So <code>-isodates</code> is more than a mere default value. 
2201    * The set of allowed options is this which preserves the form fo output 
2202    * seen without options which is like so: 
2203    * <pre>
2204    * Custom Metadata: no
2205    * Metadata Stream: yes
2206    * Tagged:          yes
2207    * UserProperties:  no
2208    * Suspects:        no
2209    * Form:            none
2210    * JavaScript:      no
2211    * Pages:           204
2212    * Encrypted:       no
2213    * Page size:       595.276 x 841.89 pts (A4)
2214    * Page rot:        0
2215    * File size:       1925974 bytes
2216    * Optimized:       no
2217    * PDF version:     2.0
2218    * <pre>
2219    * To be more precise, each line has the form <code>&lt;key&gt;:&lt;blanks&gt;&lt;value&lt;</code>. 
2220    * This allows only options referring to dates, passwords and with some restrictions box, 
2221    * and ranges (making pages explicit). 
2222    * TBD: rework 
2223    */
2224   @RuntimeParameter
2225   @Parameter(name = "pdfMetainfoOptions", defaultValue = "-isodates")
2226   private String pdfMetainfoOptions = "-isodates";
2227 
2228   /**
2229    * The options to retrieve XMP metadata for the command {@link #pdfMetainfoCommand}
2230    * which is currently always <code>pdfinfo</code>. 
2231    * For <code>pdfinfo</code> the option <code>-meta</code> is mandatory 
2232    * and seemingly it does not make sense to combine with something else. 
2233    * TBD: rework 
2234    */
2235   @RuntimeParameter
2236   @Parameter(name = "pdfMetainfoXmpOptions", defaultValue = "-meta")
2237   private String pdfMetainfoXmpOptions = "-meta";
2238   
2239 
2240   /**
2241    * The latexmk command to create a pdf-file from a latex file and other files. 
2242    * The default value is <code>latexmk</code> there will be hardly a reason to change it. 
2243    * Conceivable is a wrapper around, unlikely is a reimplementation. 
2244    */
2245   @RuntimeParameter
2246   @Parameter(name = "latexmkCommand", defaultValue = "latexmk")
2247   private String latexmkCommand = "latexmk";
2248 
2249   /**
2250    * The options for the command {@link #latexmkCommand}. 
2251    * Since this command is controlled 
2252    * to a wide extend by the config file <code>.latexmkrc</code>, 
2253    * the options are of minor importance. 
2254    * On the other hand, there are options not allowed for this software 
2255    * because they change behavior in a way not taken into account. 
2256    * So add options with care. 
2257    * The default value is the empty string. 
2258    */
2259   @RuntimeParameter
2260   @Parameter(name = "latexmkOptions", defaultValue = "")
2261   private String latexmkOptions = "";
2262 
2263   /**
2264    * The command for a tool to verify a PDF standard, 
2265    * which is one of kinds of PDF/A, PDF/X or PDF/UA at the time of this writing 
2266    * or some else in future. 
2267    * It must provide return values 
2268    * <ul>
2269    * <li> 0 for check executed and passed, 
2270    * <li> 1 executed but failed, 
2271    * <li> and possibly other codes indicating that the test could not be executed, 
2272    * i.e. a failure, these must be in 2-12 except 5. 
2273    * <ul>
2274    * The default value is <code>verapdf</code> 
2275    * and the according default options {@link #verifyStdOptions} are adapted to this. 
2276    * 
2277    */
2278   @RuntimeParameter
2279   @Parameter(name = "verifyStdCommand", defaultValue = "verapdf")
2280   private String verifyStdCommand = "verapdf";
2281 
2282   /**
2283    * The options for the command {@link #verifyStdCommand}. 
2284    * The default value is adapted to the default command. 
2285    * Since in the given context, 
2286    * it is the TEX file itself which determines the standard(s) 
2287    * it shall conform with via
2288    * 
2289    * <pre>
2290    * \DocumentMetadata{...pdfstandard=}
2291    * </pre>
2292    * 
2293    * one shall neither give a profile via <code>--profile</code> or that like, 
2294    * nor a flavor via <code>--defaultflavor</code> or <code>--flavor</code> 
2295    * except flavor 0 which means, 
2296    * use flavor determined by the PDF file itself, 
2297    * which is what is specified in the according TEX file. 
2298    * For obvious reason, <code>--off</code>, <code>--help</code>, 
2299    * <code>--list</code> and <code>--version</code> 
2300    * are not allowed either. 
2301    * <p>
2302    * Note that <code>--format</code> is set to <code>text</code> 
2303    * because this shows only the standards checked and the result as pass or fail. 
2304    * This is appropriate to get a true overview. 
2305    * This shall be kept but it is possible to add further options. 
2306    */
2307   @RuntimeParameter
2308   @Parameter(name = "verifyStdOptions", defaultValue = "-f 0 --format text")
2309   private String verifyStdOptions = "-f 0 --format text";
2310 
2311   /**
2312    * Whether verification can be done implicitly by comparison. 
2313    * Means, if for an actually created artifact, 
2314    * <ul>
2315    * <li> a comparison with an original is requested either by a magic comment for the latex main file individually 
2316    *      or, if not specified, globally, by {@link #chkDiff} 
2317    * <li> this original artifact exists, means is stored at proper place, so that the comparison is executed and 
2318    * <li> the comparison between actually created file and original one confirms equality
2319    * </ul>
2320    * then it is assumed, that the original file had been verified and so comparison validates the actual artifact 
2321    * and need not longer be verified using {@link #verifyStdCommand}. 
2322    * Setting this to <code>false</code> forces explicit verification. 
2323    * The default value is <code>true</code>. 
2324    */
2325   @RuntimeParameter
2326   @Parameter(name = "verifyByCmp", defaultValue = "true")
2327   private boolean verifyByCmp = true;
2328 
2329 
2330   //TBD: add options; 
2331   // diff: no sensible options are available. 
2332   // diff-pdf same
2333   // diff-pdf-visually same
2334   // getter methods partially implementing default values. 
2335 
2336 
2337   // private File getBaseDirectory() throws BuildFailureException {
2338   // 	if (!(this.baseDirectory.exists() && 
2339   // 	      this.baseDirectory.isDirectory())) {
2340   // 	    throw new BuildFailureException
2341   // 		("The base directory '" + this.baseDirectory + 
2342   // 		 "' should be an existing directory, but is not. ");
2343   // 	}
2344   // 	return this.baseDirectory;
2345   // }
2346 
2347   // private File getTargetDirectory() {
2348   //     return this.targetDirectory;
2349   // }
2350 
2351   // private File getTargetSiteDirectory() {
2352   //     return this.targetSiteDirectory;
2353   // }
2354 
2355   /**
2356    *
2357    * @throws BuildFailureException 
2358    *    TSS01 if the tex source directory does either not exist 
2359    *    or is not a directory. 
2360    */
2361   // used in LatexProcessor only: 
2362   // .create() to determine the output directory of the created files 
2363   public File getTexSrcDirectoryFile() throws BuildFailureException {
2364     if (!(this.texSrcDirectoryFile.exists()
2365         && this.texSrcDirectoryFile.isDirectory())) {
2366       throw new BuildFailureException(
2367           "TSS01: The tex source directory '" + this.texSrcDirectoryFile
2368               + "' should be an existing directory, but is not. ");
2369     }
2370     return this.texSrcDirectoryFile;
2371   }
2372 
2373   /**
2374    *
2375    * @throws BuildFailureException 
2376    *    TSS02 if the tex source processing directory does either not exist 
2377    *    or is not a directory. 
2378    */
2379   // used in LatexProcessor only: 
2380   // .create() to determine which directories to be processed 
2381   // .processGraphics() to get all graphics files 
2382   // .clearAll() 
2383   public File getTexSrcProcDirectoryFile() throws BuildFailureException {
2384     if (!(this.texSrcProcDirectoryFile.exists()
2385         && this.texSrcProcDirectoryFile.isDirectory())) {
2386       throw new BuildFailureException(
2387           "TSS02: The tex source processing directory '"
2388               + this.texSrcProcDirectoryFile
2389               + "' should be an existing directory, but is not. ");
2390     }
2391 
2392     return this.texSrcProcDirectoryFile;
2393   }
2394 
2395   public boolean getReadTexSrcProcDirRec() {
2396     return this.readTexSrcProcDirRec;
2397   }
2398 
2399   /**
2400    *
2401    * @throws BuildFailureException 
2402    *    TSS03 if the output directory exists and is no directory. 
2403    */
2404   public File getOutputDirectoryFile() throws BuildFailureException {
2405     if (/**/this.outputDirectoryFile.exists()
2406         && !this.outputDirectoryFile.isDirectory()) {
2407       throw new BuildFailureException(
2408           "TSS03: The output directory '" + this.outputDirectoryFile
2409               + "' should be a directory if it exists, but is not. ");
2410     }
2411     return this.outputDirectoryFile;
2412   }
2413 
2414   /**
2415    *
2416    * @throws BuildFailureException 
2417    *    TSS09 if the diff directory exists and is no directory. 
2418    */
2419   public File getDiffDirectoryFile() throws BuildFailureException {
2420     if (/**/this.diffDirectoryFile.exists()
2421         && !this.diffDirectoryFile.isDirectory()) {
2422       throw new BuildFailureException(
2423           "TSS09: The diff directory '" + this.diffDirectoryFile
2424               + "' should be a directory if it exists, but is not. ");
2425     }
2426     return this.diffDirectoryFile;
2427   }
2428 
2429   /**
2430    * Returns the set of targets. 
2431    *
2432    * @return
2433    *     The set of targets.
2434    * @throws BuildFailureException
2435    *    TSS04 if the target set is not a subset
2436    *    of the set given by {@link Target}.
2437    */
2438   // TBD: ordering must be clarified 
2439   public SortedSet<Target> getTargets() throws BuildFailureException {
2440     return getTargets(this.targets, TargetsContext.targetsSetting);
2441   }
2442 
2443   /**
2444    * Returns the targets given by the string <code>targetsChunkStr</code> 
2445    * as a set of {@link Target}s. 
2446    * If the target string is invalid an exception is thrown 
2447    * with a message influenced by <code>targetContext</code> 
2448    * which depends on the context in which this method is invoked. 
2449    * 
2450    * @param targetsChunksStr
2451    *    The target string of all targets. 
2452    *    TBD: simplify name. 
2453    * @param targetContext
2454    *    specifies the context in which this method is invoked 
2455    *    and contributes this context to the message of a thrown exception, if any. 
2456    *    Else this value has no effect. 
2457    * @return
2458    *     The set of targets given by <code>targetsChunksStr</code>.
2459    * @throws BuildFailureException
2460    *    <ul>
2461    *    <li>TSS04 if <code>targetsChunkStr</code> is invalid 
2462    *    <li>TSS11 if a target in <code>targetsChunkStr</code> occurs more than once 
2463    *    </ul>
2464    * @see #getTargets()
2465    * @see #getDocClassesToTargets()
2466    * @see LatexProcessor#create(SortedSet)
2467    */
2468   static SortedSet<Target> getTargets(String targetsChunksStr, TargetsContext targetContext)
2469       throws BuildFailureException {
2470 
2471     // TreeSet is sorted. maybe this determines ordering of targets. 
2472     SortedSet<Target> targetsSet = new TreeSet<Target>();
2473     if (targetsChunksStr.isEmpty()) {
2474       return targetsSet;
2475     }
2476     String[] targetSeq = targetsChunksStr.split(",");
2477     for (int idx = 0; idx < targetSeq.length; idx++) {
2478       assert targetSeq[idx] != null;
2479       String targetStr = targetSeq[idx];
2480       // may throw BuildFailureException TSS04 and TSS11 
2481       readTargetChecked(targetStr, targetsSet, targetsChunksStr, targetContext);
2482     } // for 
2483     return targetsSet;
2484   }
2485 
2486   /**
2487    * Converts <code>targetStr</code> into a {@link Target} 
2488    * and adds it to <code>targetSet</code> if possible. 
2489    * An exception is thrown if <code>targetStr</code> is either no valid target 
2490    * or if it is a target already in <code>targetSet</code>. 
2491    * Parameter <code>targetsStr</code> is only used 
2492    * to create the message of the exceptions thrown. 
2493    * 
2494    * @param targetStr
2495    *    The target to be added 
2496    * @param targetsSet
2497    *    The target set the target to <code>targetStr</code> must be added. 
2498    * @param targetsChunksStr
2499    *    The target string of all targets: <code>targetStr</code> is part. 
2500    *    This is needed for the message of the exception. 
2501    * @param targetsContext
2502    *    specifies the context in which this method is invoked 
2503    *    and contributes this context to the message of a thrown exception, if any. 
2504    *    Else this value has no effect. 
2505    * @throws BuildFailureException
2506    *    <ul>
2507    *    <li>TSS04 if targetStr is invalid 
2508    *    <li>TSS11 if target for targetStr already in targetsSet
2509    *    </ul>
2510    */
2511   private static void readTargetChecked(String targetStr,
2512                                         Set<Target> targetsSet, 
2513                                         String targetsChunksStr, 
2514                                         TargetsContext targetsContext)
2515                 throws BuildFailureException {
2516     try {
2517       Target target = Target.valueOf(targetStr);
2518       // may not throw an IllegalArgumentException
2519       boolean isNew = targetsSet.add(target);
2520       if (!isNew) {
2521         throw new BuildFailureException("TSS11: The target set '" + targetsChunksStr
2522           + "' in " + targetsContext.context()
2523           + " repeats target '" + target + "'. ");
2524       }
2525     } catch (IllegalArgumentException ae) {
2526       // Here, targetStr does not contain the name of a Target 
2527       assert Target.class.isEnum();
2528       throw new BuildFailureException("TSS04: The target set '" + targetsChunksStr
2529           + "' in " + targetsContext.context()
2530           + " contains the invalid target '" + targetStr + "'. ");
2531     } // catch 
2532   }
2533 
2534   // public SortedSet<Target> getTargets() throws BuildFailureException {
2535   //   return this.targets;
2536   // }
2537 
2538   // TBD: maybe better: store allowed converters. 
2539   // TBD: maybe better: cache converters read. 
2540   /**
2541    * Returns the set of converters excluded from usage. 
2542    *
2543    * @return
2544    *     The set of converters excluded from usage. 
2545    * @throws BuildFailureException 
2546    *    TSS05 if set of converters excluded from usage 
2547    *    is not a subset of the set given by {@link Converter}. 
2548    */
2549   public SortedSet<Converter> getConvertersExcluded()
2550       throws BuildFailureException {
2551     SortedSet<Converter> convSet = new TreeSet<Converter>();
2552     if (this.convertersExcluded.isEmpty()) {
2553       return convSet;
2554     }
2555     String[] convSeq = this.convertersExcluded.split(" *, *");
2556     for (int idx = 0; idx < convSeq.length; idx++) {
2557       Converter conv = Converter.cmd2Conv(convSeq[idx]);
2558       if (conv == null) {
2559         // Here, the converter given is unknown.
2560         throw new BuildFailureException(
2561             "TSS05: The excluded converters '" + this.convertersExcluded
2562                 + "' should form a subset of the registered converters '"
2563                 + Converter.toCommandsString() + "'. ");
2564       }
2565       convSet.add(conv);
2566     }
2567     return convSet;
2568   }
2569 
2570   /**
2571    * Returns the converter name which is typically <code>convStr</code> 
2572    * and throws an exception if the converter given is invalid. 
2573    *
2574    * @param convStr
2575    *    the name of a converter as a string as given in the configuration. 
2576    *    If this converter is registered with this software, 
2577    *    i.e. if it corresponds with an instance of {@link Converter}, 
2578    *    then it is given just by {@link Converter#getCommand()}. 
2579    *    Else, it must be given in the form <code>commandName:category</code>, 
2580    *    where <code>category</code> is given by <code>cat</code> 
2581    *    via {@link ConverterCategory#getExtName()}. 
2582    * @throws BuildFailureException
2583    *    In case the converter is given directly, as if registered: 
2584    *    <ul>
2585    *    <li>TSS06 if 
2586    *    tried to use converter not registered. </li>
2587    *    <li>TSS05 if 
2588    *    the set of converters excluded from usage 
2589    *    is not a subset of the set given by {@link Converter}. </li>
2590    *    <li>TSS07 if 
2591    *    tried to use converter which is among the excluded ones. </li>
2592    *    <li>TSS08 if 
2593    *    tried to use converter within wrong category. </li>
2594    *     <li>
2595    *    tried to use converter within wrong category. </li>
2596    *    </ul>
2597    *    TSS10 if the converter is given in the form 
2598    *    <code>&lt;cat1Command&gt;commandName:cat2&lt;/cat1Command&gt;</code> 
2599    *    with <code>cat2</code> not coinciding with <code>cat1</code>. 
2600    * @return
2601    *    the proper name of the converter. 
2602    *    If the converter is registered with this software, 
2603    *    then just <code>convStr</code> is returned. 
2604    *    Else <code>convStr</code> has the form <code>commandName:category</code> 
2605    *    and what is returned is the proper name <code>commandName</code>. 
2606    */
2607   private String checkConverterName(String convStr, ConverterCategory cat)
2608       throws BuildFailureException {
2609     int idxLastCol = convStr.lastIndexOf(':');
2610     if (idxLastCol != -1) {
2611       // Here, the converter is not registered 
2612       // and so it is given in the form
2613       // converterName:category
2614       String catStr = convStr.substring(idxLastCol + 1);
2615       String convStrProper = convStr.substring(0, idxLastCol);
2616       if (!cat.getExtName().equals(catStr)) {
2617         throw new BuildFailureException(
2618             "TSS10: Specified unregistered converter '" + convStrProper
2619                 + "' with invalid category '" + catStr + "'; should be '"
2620                 + cat.getExtName() + "''. ");
2621       }
2622       return convStrProper;
2623     }
2624 
2625     // Here, no colon occurs and the converter is registered.
2626 
2627     Converter conv = Converter.cmd2Conv(convStr);
2628     if (conv == null) {
2629       throw new BuildFailureException("TSS06: Tried to use converter '"
2630           + convStr + "' although not among the registered converters '"
2631           + Converter.toCommandsString() + "' as expected. ");
2632     }
2633     // may throw BuildFailureException TSS05
2634     SortedSet<Converter> convertersExcluded = getConvertersExcluded();
2635     if (convertersExcluded.contains(conv)) {
2636       throw new BuildFailureException("TSS07: Tried to use converter '"
2637           + convStr + "' although among the excluded converters '"
2638           + Converter.toCommandsString(convertersExcluded) + "'. ");
2639     }
2640     if (conv.getCategory() != cat) {
2641       throw new BuildFailureException(
2642           "TSS08: Tried to use converter '" + convStr + "' in configuration '"
2643               + cat.getCommandFieldname() + "' instead of configuration '"
2644               + conv.getCategory().getCommandFieldname() + "'. ");
2645     }
2646     return convStr;
2647   }
2648 
2649   public String getPatternLatexMainFile() {
2650     return this.patternLatexMainFile;
2651   }
2652 
2653   // TBD: invocation at the wrong place: thus is invoked for each target anew. 
2654   /**
2655    * 
2656    * @return
2657    * @throws BuildFailureException
2658    *    TSS01, TSS11
2659    */
2660   public Map<String, Set<Target>> getDocClassesToTargets()
2661       throws BuildFailureException {
2662 
2663     Map<String, Set<Target>> result = new TreeMap<String, Set<Target>>();
2664     String[] chunks = this.docClassesToTargets.trim().split("\\s+");
2665     int idxCol1, idxCol2;
2666     String classesStr;
2667     Set<Target> targetsSet, oldTargetSet;
2668     for (String chunk : chunks) {
2669       idxCol1 = chunk.indexOf(':');
2670       idxCol2 = chunk.lastIndexOf(':');
2671       if (idxCol1 == -1 || idxCol1 == 0 || idxCol1 != idxCol2) {
2672         // Here, either 
2673         // - no colon exists (idxCol1 == -1 (which implies also idxCol2 == -1)) 
2674         // - or more than one colon exists (idxCol1 != idxCol2)
2675         // - or the colon is at the the 0th place (idxCol1 == 0)
2676         // Note that the colon may be at the last place 
2677         // indicating that the given document classes (preceding the colon) 
2678         // are not processed at all. 
2679         throw new BuildFailureException("TSS12: Invalid mapping '" + chunk
2680             + "' of document classes to targets. ");
2681       }
2682 
2683       String targetsStr = chunk.substring(idxCol1 + 1);
2684       targetsSet = getTargets(targetsStr, TargetsContext.inChunkSetting);
2685 
2686 
2687       classesStr = chunk.substring(0, idxCol1);
2688       //System.out.println("classesStr: '" + classesStr + "'");
2689       // TBD: check maven bug MNG-7927 still present. 
2690       // For details search through the manual. 
2691       for (String cls : classesStr.split(",")) {
2692         oldTargetSet = result.put(cls, targetsSet);
2693         if (oldTargetSet != null) {
2694           throw new BuildFailureException
2695           ("TSS13: For document class '" + cls
2696               + "' target set is not unique. ");
2697         }
2698       }
2699      } // chunks 
2700 
2701     return result;
2702   }
2703 
2704   public Set<String> getMainFilesIncluded() {
2705     return this.mainFilesIncluded.isEmpty() ? new HashSet<String>()
2706         : new HashSet<String>(Arrays.asList(this.mainFilesIncluded.split(" ")));
2707   }
2708 
2709   public Set<String> getMainFilesExcluded() {
2710     return this.mainFilesExcluded.isEmpty() ? new HashSet<String>()
2711         : new HashSet<String>(Arrays.asList(this.mainFilesExcluded.split(" ")));
2712   }
2713 
2714 
2715   public LatexmkUsage getLatexmkUsage() {
2716     return this.latexmkUsage;
2717   }
2718 
2719   // texPath, commands and arguments 
2720 
2721   public File getTexPath() {
2722     return this.texPath;
2723   }
2724 
2725   public boolean isCleanUp() {
2726     return this.cleanUp;
2727   }
2728 
2729   public boolean isChkDiff() {
2730     return this.chkDiff;
2731   }
2732 
2733   public String getPatternCreatedFromLatexMain() {
2734     return this.patternCreatedFromLatexMain;
2735   }
2736 
2737   // for ant task only 
2738   @RuntimeParameter
2739   public String getFig2devCommand() throws BuildFailureException {
2740     return getCommand(ConverterCategory.Fig2Dev);
2741   }
2742 
2743   public String getFig2devGenOptions() {
2744     return this.fig2devGenOptions;
2745   }
2746 
2747   public String getFig2devPtxOptions() {
2748     return this.fig2devPtxOptions;
2749   }
2750 
2751   public String getFig2devPdfEpsOptions() {
2752     return this.fig2devPdfEpsOptions;
2753   }
2754 
2755   // for ant task only 
2756   @RuntimeParameter
2757   public String getGnuplotCommand() throws BuildFailureException {
2758     return getCommand(ConverterCategory.Gnuplot2Dev);
2759   }
2760 
2761   public String getGnuplotOptions() {
2762     return this.gnuplotOptions;
2763   }
2764 
2765   // for ant task only 
2766   @RuntimeParameter
2767   public String getMetapostCommand() throws BuildFailureException {
2768     return getCommand(ConverterCategory.MetaPost);
2769   }
2770 
2771   public String getMetapostOptions() {
2772     return this.metapostOptions;
2773   }
2774 
2775   // same pattern as for latex 
2776   public String getPatternErrMPost() {
2777     return this.patternErrMPost;
2778   }
2779 
2780   // same pattern as for latex 
2781   // FIXME: counterexample
2782   //Preloading the plain mem file, version 1.005) ) (./F4_05someMetapost.mp
2783   // Warning: outputtemplate=0: value has the wrong type, assignment ignored.
2784   public String getPatternWarnMPost() {
2785     return this.patternWarnMPost;
2786   }
2787 
2788   // for ant task only 
2789   @RuntimeParameter
2790   public String getSvg2devCommand() throws BuildFailureException {
2791     return getCommand(ConverterCategory.Svg2Dev);
2792   }
2793 
2794   public String getSvg2devOptions() {
2795     return this.svg2devOptions;
2796   }
2797 
2798   public boolean getCreateBoundingBoxes() {
2799     return this.createBoundingBoxes;
2800   }
2801 
2802   // for ant task only 
2803   @RuntimeParameter
2804   public String getEbbCommand() throws BuildFailureException {
2805     return getCommand(ConverterCategory.EbbCmd);
2806   }
2807 
2808   public String getEbbOptions() {
2809     return this.ebbOptions;
2810   }
2811 
2812   @RuntimeParameter
2813   public String getLatex2pdfCommand() throws BuildFailureException {
2814     return getCommand(ConverterCategory.LaTeX);
2815   }
2816 
2817 
2818   // FIXME: to be renamed: texOptions 
2819   public String getLatex2pdfOptions() {
2820     return this.latex2pdfOptions;
2821   }
2822 
2823   public String getPatternErrLatex() {
2824     return this.patternErrLatex;
2825   }
2826 
2827   public String getPatternWarnLatex() {
2828     return this.patternWarnLatex;
2829   }
2830 
2831   public boolean getDebugBadBoxes() {
2832     return this.debugBadBoxes;
2833   }
2834 
2835   public boolean getDebugWarnings() {
2836     return this.debugWarnings;
2837   }
2838 
2839   public LatexDev getPdfViaDvi() {
2840     return LatexDev.devViaDvi(this.pdfViaDvi);
2841   }
2842 
2843   @RuntimeParameter
2844   public String getDvi2pdfCommand() throws BuildFailureException {
2845     return getCommand(ConverterCategory.Dvi2Pdf);
2846   }
2847 
2848   public String getDvi2pdfOptions() {
2849     return this.dvi2pdfOptions;
2850   }
2851 
2852   public String getPatternReRunLatex() {
2853     return this.patternReRunLatex;
2854   }
2855 
2856   public int getMaxNumReRunsLatex() {
2857     return this.maxNumReRunsLatex;
2858   }
2859 
2860   // TBD: check category 
2861 
2862   // TBD: refer to annotation, not to field name. 
2863   /**
2864    * TBD: add docs 
2865    *
2866    * @throws BuildFailureException 
2867    *    <ul>
2868    *    <li>TSS06 if 
2869    *    tried to use converter not registered. </li>
2870    *    <li>TSS05 if 
2871    *    set of converters excluded from usage 
2872    *    is not a subset of the set given by {@link Converter}. </li>
2873    *    <li>TSS07 if 
2874    *    tried to use converter which is among the excluded ones. </li>
2875    *    <li>TSS08 if 
2876    *    tried to use converter within wrong category. </li>
2877    *    </ul>
2878    */
2879   public String getCommand(ConverterCategory cat) throws BuildFailureException {
2880     String cmdName;
2881     try {
2882       cmdName = (String) this.getClass()
2883           .getDeclaredField(cat.getCommandFieldname()).get(this);
2884     } catch (NoSuchFieldException nsfe) {
2885       throw new IllegalStateException("Could not find field '"
2886           + cat.getCommandFieldname() + "' in Settings. ");
2887     } catch (IllegalAccessException iace) {
2888       throw new IllegalStateException(
2889           "Parameter '" + cat.getCommandFieldname() + "' not readable. ");
2890     } catch (IllegalArgumentException iage) {
2891       throw new IllegalStateException("Settings class mismatch. ");
2892     }
2893     // may throw BuildFailureException TSS05-08
2894 
2895     cmdName = checkConverterName(cmdName, cat);// replace by checked cmdName
2896     return cmdName;
2897   }
2898 
2899   // for ant task only 
2900   @RuntimeParameter
2901   public String getBibtexCommand() throws BuildFailureException {
2902     return getCommand(ConverterCategory.BibTeX);
2903   }
2904 
2905   public String getBibtexOptions() {
2906     return this.bibtexOptions;
2907   }
2908 
2909   public String getPatternErrBibtex() {
2910     return this.patternErrBibtex;
2911   }
2912 
2913   public String getPatternWarnBibtex() {
2914     return this.patternWarnBibtex;
2915   }
2916 
2917   // for indices 
2918 
2919   public String getPatternMultiIndex() {
2920     return this.patternMultiIndex;
2921   }
2922 
2923   // for ant task only 
2924   @RuntimeParameter
2925   public String getMakeIndexCommand() throws BuildFailureException {
2926     return getCommand(ConverterCategory.MakeIndex);
2927   }
2928 
2929   public String getMakeIndexOptions() {
2930     return this.makeIndexOptions;
2931   }
2932 
2933   public String getPatternErrMakeIndex() {
2934     return this.patternErrMakeIndex;
2935   }
2936 
2937   public String getPatternWarnMakeIndex() {
2938     return this.patternWarnMakeIndex;
2939   }
2940 
2941   // for ant task only 
2942   @RuntimeParameter
2943   public String getSplitIndexCommand() throws BuildFailureException {
2944     return getCommand(ConverterCategory.SplitIndex);
2945   }
2946 
2947   public String getSplitIndexOptions() {
2948     return this.splitIndexOptions;
2949   }
2950 
2951   // for ant task only 
2952   @RuntimeParameter
2953   public String getMakeGlossariesCommand() throws BuildFailureException {
2954     return getCommand(ConverterCategory.MakeGlossaries);
2955   }
2956 
2957   public String getMakeGlossariesOptions() {
2958     return this.makeGlossariesOptions;
2959   }
2960 
2961   public String getPatternWarnXindy() {
2962     return this.patternWarnXindy;
2963   }
2964 
2965   public String getPatternErrXindy() {
2966     return this.patternErrXindy;
2967   }
2968 
2969 
2970   // for ant task only 
2971   @RuntimeParameter
2972   public String getPythontexCommand() throws BuildFailureException {
2973     return getCommand(ConverterCategory.Pythontex);
2974   }
2975 
2976   public String getPythontexOptions() {
2977     return this.pythontexOptions;
2978   }
2979 
2980   public String getPatternErrPyTex() {
2981     return this.patternErrPyTex;
2982   }
2983 
2984   public String getPatternWarnPyTex() {
2985     return this.patternWarnPyTex;
2986   }
2987 
2988   public String getPrefixPytexOutFolder() {
2989     return this.prefixPytexOutFolder;
2990   }
2991 
2992   // TBD: check category . shall be replaced by getCommand(ConverterCategory)
2993   //@RuntimeParameter
2994   public String getTex4htCommand() {
2995     //Converter conv = Converter.cmd2Conv(this.tex4htCommand, ConverterCategory.LaTeX2Html);
2996     // TBD: check: this has two categories: tex2html and tex2odt 
2997     return this.tex4htCommand;
2998   }
2999 
3000   public String getTex4htStyOptions() {
3001     return this.tex4htStyOptions;
3002   }
3003 
3004   public String getTex4htOptions() {
3005     return this.tex4htOptions;
3006   }
3007 
3008   public String getT4htOptions() {
3009     return this.t4htOptions;
3010   }
3011 
3012   public String getPatternT4htOutputFiles() {
3013     return this.patternT4htOutputFiles;
3014   }
3015 
3016   // for ant task only 
3017   //@RuntimeParameter
3018   public String getLatex2rtfCommand() throws BuildFailureException {
3019     return getCommand(ConverterCategory.LaTeX2Rtf);
3020   }
3021 
3022   public String getLatex2rtfOptions() {
3023     return this.latex2rtfOptions;
3024   }
3025 
3026   //@RuntimeParameter
3027   public String getOdt2docCommand() throws BuildFailureException {
3028     return getCommand(ConverterCategory.Odt2Doc);
3029   }
3030 
3031   public String getOdt2docOptions() {
3032     return this.odt2docOptions;
3033   }
3034 
3035   // for ant task only 
3036   public String getPdf2txtCommand() throws BuildFailureException {
3037     return getCommand(ConverterCategory.Pdf2Txt);
3038   }
3039 
3040   public String getPdf2txtOptions() {
3041     return this.pdf2txtOptions;
3042   }
3043 
3044   // for ant task only 
3045   // @RuntimeParameter
3046   public String getChkTexCommand() throws BuildFailureException {
3047     return getCommand(ConverterCategory.LatexChk);
3048   }
3049 
3050   public String getChkTexOptions() {
3051     return this.chkTexOptions;
3052   }
3053 
3054 
3055   public String getVerifyStdCommand() throws BuildFailureException {
3056     return getCommand(ConverterCategory.StandardValidator);
3057   }
3058 
3059   String getVerifyStdOptions() {
3060     return this.verifyStdOptions;
3061   }
3062 
3063   boolean getVerifyByCmp() {
3064     return this.verifyByCmp;
3065   }
3066   
3067 
3068   // for ant task only if needed TBD
3069   //@RuntimeParameter
3070   public String getDiffPdfCommand() throws BuildFailureException {
3071     return getCommand(ConverterCategory.DiffPdf);
3072   }
3073 
3074   @RuntimeParameter
3075   public String getPdfMetainfoCommand() throws BuildFailureException {
3076     return getCommand(ConverterCategory.MetaInfoPdf);
3077   }
3078 
3079   public String getPdfMetainfoOptions() {
3080     return this.pdfMetainfoOptions;
3081   }
3082 
3083     public String getPdfMetainfoXmpOptions() {
3084     return this.pdfMetainfoXmpOptions;
3085   }
3086 
3087 
3088   //@RuntimeParameter
3089   public String getLatexmkCommand() throws BuildFailureException {
3090     return getCommand(ConverterCategory.Latexmk);
3091   }
3092 
3093   public String getLatexmkOptions() {
3094     return this.latexmkOptions;
3095   }
3096 
3097   // setter methods 
3098 
3099   /**
3100     * Sets {@link #baseDirectory} and updates 
3101     * {@link #texSrcDirectoryFile} and {@link #texSrcProcDirectoryFile}. 
3102     */
3103   public void setBaseDirectory(File baseDirectory) {
3104     this.baseDirectory = baseDirectory;
3105     this.texSrcDirectoryFile =
3106         new File(this.texSrcDirectory);//this.baseDirectory, 
3107     this.texSrcProcDirectoryFile =
3108         new File(this.texSrcDirectoryFile, this.texSrcProcDirectory);
3109     this.texSrcProcDirectoryFile =
3110         new File(this.texSrcDirectoryFile, this.texSrcProcDirectory);
3111     this.diffDirectoryFile = new File(this.baseDirectory, this.diffDirectory);
3112 
3113   }
3114 
3115   /**
3116    * Sets {@link #targetDirectory}. 
3117    */
3118   public void setTargetDirectory(File targetDirectory) {
3119     this.targetDirectory = targetDirectory;
3120   }
3121 
3122   /**
3123    * Sets {@link #targetSiteDirectory} and updates 
3124    * {@link #outputDirectoryFile}. 
3125    */
3126   public void setTargetSiteDirectory(File targetSiteDirectory) {
3127     this.targetSiteDirectory = targetSiteDirectory;
3128     this.outputDirectoryFile =
3129         new File(this.targetSiteDirectory, this.outputDirectory);
3130   }
3131 
3132   /**
3133    * Sets {@link #texSrcDirectory} and updates 
3134    * {@link #texSrcDirectoryFile} and {@link #texSrcProcDirectoryFile}. 
3135    */
3136   public void setTexSrcDirectory(String texSrcDirectory) {
3137     this.texSrcDirectory = texSrcDirectory;
3138     this.texSrcDirectoryFile =
3139         new File(this.texSrcDirectory);//this.baseDirectory, 
3140     this.texSrcProcDirectoryFile =
3141         new File(this.texSrcDirectoryFile, this.texSrcProcDirectory);
3142   }
3143 
3144   /**
3145    * Sets {@link #texSrcProcDirectory} and updates 
3146    * {@link #texSrcProcDirectoryFile}. 
3147    */
3148   public void setTexSrcProcDirectory(String texSrcProcDirectory) {
3149     this.texSrcProcDirectory = texSrcProcDirectory;
3150     this.texSrcProcDirectoryFile =
3151         new File(this.texSrcDirectoryFile, this.texSrcProcDirectory);
3152   }
3153 
3154   public void setReadTexSrcProcDirRec(boolean readTexSrcProcDirRec) {
3155     this.readTexSrcProcDirRec = readTexSrcProcDirRec;
3156   }
3157 
3158   /**
3159    * Sets {@link #outputDirectory} and updates {@link #outputDirectoryFile}. 
3160    */
3161   public void setOutputDirectory(String outputDirectory) {
3162     this.outputDirectory = outputDirectory;
3163     this.outputDirectoryFile =
3164         new File(this.targetSiteDirectory, this.outputDirectory);
3165   }
3166 
3167   public void setDiffDirectory(String diffDirectory) {
3168     this.diffDirectory = diffDirectory;
3169     this.diffDirectoryFile = new File(this.baseDirectory, this.diffDirectory);
3170   }
3171 
3172   // TBD: check which of these setters are really necessary 
3173   public void setTargets(String targets) {
3174     this.targets = targets.trim();
3175   }
3176   // public void setTargets(SortedSet<Target> targets) {
3177   //   this.targets = targets;
3178   // }
3179 
3180   public void setConvertersExcluded(String convertersExcluded) {
3181     this.convertersExcluded = convertersExcluded.trim();
3182   }
3183 
3184   // setter method for patternLatexMainFile in maven 
3185   // trims parameter before setting 
3186   public void setPatternLatexMainFile(String patternLatexMainFile) {
3187     // System.out.println("set pattern");
3188     // patternLatexMainFile = patternLatexMainFile.replaceAll("(\t|\n)+", "").trim();
3189     // System.out.println("lengths "+this.patternLatexMainFile.length()+" "+patternLatexMainFile.length());
3190     // int min = Math.min(this.patternLatexMainFile.length(),patternLatexMainFile.length());
3191     // for (int i = 0; i<min;i++) {
3192     //   if (this.patternLatexMainFile.codePointAt(i) != patternLatexMainFile.codePointAt(i)) {
3193     //     System.out.println("common prefix is |"+patternLatexMainFile.substring(0,i)+"|");
3194     //     System.out.println("then |"+this.patternLatexMainFile.codePointAt(i)
3195     //     +"| replaced by |"+patternLatexMainFile.codePointAt(i));
3196     //     break;
3197     //   }
3198     // }
3199     // this.patternLatexMainFile = patternLatexMainFile;
3200 
3201     this.patternLatexMainFile = patternLatexMainFile.replaceAll("(\t|\n)+", "").trim();
3202   }
3203 
3204   // method introduces patternLatexMainFile in ant 
3205   public PatternLatexMainFile createPatternLatexMainFile() {
3206     return new PatternLatexMainFile();
3207   }
3208 
3209   // defines patternLatexMainFile element with text in ant 
3210   public class PatternLatexMainFile {
3211     // FIXME: this is without property resolution.
3212     // to add this need pattern = getProject().replaceProperties(pattern)
3213     // with Task.getProject()
3214     public void addText(String pattern) {
3215       Settings.this.setPatternLatexMainFile(pattern);
3216     }
3217   } // class PatternLatexMainFile
3218 
3219   public void setDocClassesToTargets(String docClassesToTargets) {
3220     this.docClassesToTargets = docClassesToTargets;
3221   }
3222 
3223   public void setMainFilesIncluded(String mainFilesIncluded) {
3224     this.mainFilesIncluded =
3225         mainFilesIncluded.replaceAll("(\t|\n| )+", " ").trim();
3226   }
3227 
3228   public void setMainFilesExcluded(String mainFilesExcluded) {
3229     this.mainFilesExcluded =
3230         mainFilesExcluded.replaceAll("(\t|\n| )+", " ").trim();
3231   }
3232 
3233   public void setLatexmkUsage(LatexmkUsage latexmkUsage) {
3234     this.latexmkUsage = latexmkUsage;
3235   }
3236 
3237 
3238   public void setTexPath(File texPath) {
3239     this.texPath = texPath;
3240   }
3241 
3242   public void setCleanUp(boolean cleanUp) {
3243     this.cleanUp = cleanUp;
3244   }
3245 
3246   public void setChkDiff(boolean chkDiff) {
3247     this.chkDiff = chkDiff;
3248   }
3249 
3250   // FIXME: as patternCreatedFromLatexMain 
3251   // replace "\n" (canonical newline in xml) also for other patterns by ""
3252 
3253   // setter method for patternCreatedFromLatexMain in maven 
3254   // eliminates tab, newline and blanks and trims parameter before setting 
3255   public void setPatternCreatedFromLatexMain(String pattern) {
3256     this.patternCreatedFromLatexMain =
3257         pattern.replaceAll("(\t|\n| )+", "").trim();
3258   }
3259 
3260   // method introduces patternCreatedFromLatexMain in ant 
3261   public PatternCreatedFromLatexMain createPatternCreatedFromLatexMain() {
3262     return new PatternCreatedFromLatexMain();
3263   }
3264 
3265   // defines patternCreatedFromLatexMain element with text in ant 
3266   public class PatternCreatedFromLatexMain {
3267     // FIXME: this is without property resolution. 
3268     // to add this need  pattern = getProject().replaceProperties(pattern)
3269     // with Task.getProject() 
3270     public void addText(String pattern) {
3271       Settings.this.setPatternCreatedFromLatexMain(pattern);
3272     }
3273   } // class PatternCreatedFromLatexMain
3274 
3275   // note: setters are required for ant tasks 
3276   public void setFig2devCommand(String fig2devCommand) {
3277     this.fig2devCommand = fig2devCommand;
3278   }
3279 
3280   private static String beautifyOptions(String rawOption) {
3281     return rawOption.replaceAll("(\t|\n| )+", " ").trim();
3282   }
3283 
3284   public void setFig2devGenOptions(String fig2devGenOptions) {
3285     this.fig2devGenOptions = beautifyOptions(fig2devGenOptions);
3286   }
3287 
3288   public void setFig2devPtxOptions(String fig2devPtxOptions) {
3289     this.fig2devPtxOptions = beautifyOptions(fig2devPtxOptions);
3290   }
3291 
3292   public void setFig2devPdfEpsOptions(String fig2devPdfEpsOptions) {
3293     this.fig2devPdfEpsOptions = beautifyOptions(fig2devPdfEpsOptions);
3294   }
3295 
3296   public void setGnuplotCommand(String gnuplotCommand) {
3297     this.gnuplotCommand = gnuplotCommand;
3298   }
3299 
3300   public void setGnuplotOptions(String gnuplotOptions) {
3301     this.gnuplotOptions = beautifyOptions(gnuplotOptions);
3302   }
3303 
3304   public void setMetapostCommand(String metapostCommand) {
3305     this.metapostCommand = metapostCommand;
3306   }
3307 
3308   // setter method for metapostOptions in maven 
3309   public void setMetapostOptions(String metapostOptions) {
3310     this.metapostOptions = beautifyOptions(metapostOptions);
3311   }
3312 
3313   // method introduces metapostOptions in ant 
3314   public MetapostOptions createMetapostOptions() {
3315     return new MetapostOptions();
3316   }
3317 
3318   // defines e element with text in ant 
3319   public class MetapostOptions {
3320     // FIXME: this is without property resolution. 
3321     // to add this need  pattern = getProject().replaceProperties(pattern)
3322     // with Task.getProject() 
3323     public void addText(String args) {
3324       Settings.this.setMetapostOptions(args);
3325     }
3326   }
3327 
3328   // same pattern as for latex 
3329   public void setPatternErrMPost(String patternErrMPost) {
3330     this.patternErrMPost = patternErrMPost;
3331   }
3332 
3333   // not same pattern as for latex. 
3334   // in particular, not dependent on library, hm.. mostly? 
3335   // Example: 
3336   // Preloading the plain mem file, version 1.005) ) (./F4_05someMetapost.mp
3337   // Warning: outputtemplate=0: value has the wrong type, assignment ignored.
3338   public void setPatternWarnMPost(String patternWarnMPost) {
3339     this.patternWarnMPost = patternWarnMPost;
3340   }
3341 
3342   public void setSvg2devCommand(String svg2devCommand) {
3343     this.svg2devCommand = svg2devCommand;
3344   }
3345 
3346   public void setSvg2devOptions(String svg2devOptions) {
3347     this.svg2devOptions = beautifyOptions(svg2devOptions);
3348   }
3349 
3350   public void setCreateBoundingBoxes(boolean createBoundingBoxes) {
3351     this.createBoundingBoxes = createBoundingBoxes;
3352   }
3353 
3354   public void setEbbCommand(String ebbCommand) {
3355     this.ebbCommand = ebbCommand;
3356   }
3357 
3358   public void setEbbOptions(String ebbOptions) {
3359     this.ebbOptions = beautifyOptions(ebbOptions);
3360   }
3361 
3362   public void setLatex2pdfCommand(String latex2pdfCommand) {
3363     this.latex2pdfCommand = latex2pdfCommand;
3364   }
3365 
3366   /**
3367    * Sets the argument string of the latex command 
3368    * given by {@link #latex2pdfCommand}. 
3369    * It is ensured that {@link #latex2pdfOptions} 
3370    * consist of proper options separated by a single blank. 
3371    *
3372    * @param args
3373    *    The arguments string to use when calling LaTeX 
3374    *    via {@link #latex2pdfCommand}. 
3375    *    Leading and trailing blank and newline are ignored. 
3376    *    Proper arguments are separated by blank and newline. 
3377    */
3378   // setter method for latex2pdfOptions in maven 
3379   public void setLatex2pdfOptions(String args) {
3380     this.latex2pdfOptions = beautifyOptions(args);
3381   }
3382 
3383   // method introduces latex2pdfOptions in ant 
3384   public Latex2pdfOptions createLatex2pdfOptions() {
3385     return new Latex2pdfOptions();
3386   }
3387 
3388   // defines e element with text in ant 
3389   public class Latex2pdfOptions {
3390     // FIXME: this is without property resolution. 
3391     // to add this need  pattern = getProject().replaceProperties(pattern)
3392     // with Task.getProject() 
3393     public void addText(String args) {
3394       Settings.this.setLatex2pdfOptions(args);
3395     }
3396   }
3397 
3398   // setter method for patternErrLatex in maven 
3399   public void setPatternErrLatex(String patternErrLatex) {
3400     this.patternErrLatex = patternErrLatex;
3401   }
3402 
3403   // method introduces patternErrLatex in ant 
3404   public PatternErrLatex createPatternErrLatex() {
3405     return new PatternErrLatex();
3406   }
3407 
3408   // defines patternErrLatex element with text in ant 
3409   public class PatternErrLatex {
3410     // FIXME: this is without property resolution. 
3411     // to add this need  pattern = getProject().replaceProperties(pattern)
3412     // with Task.getProject() 
3413     public void addText(String pattern) {
3414       Settings.this.setPatternErrLatex(pattern);
3415     }
3416   }
3417 
3418   // setter method for patternWarnLatex in maven 
3419   public void setPatternWarnLatex(String patternWarnLatex) {
3420     this.patternWarnLatex = patternWarnLatex.replaceAll("(\t|\n)+", "").trim();
3421   }
3422 
3423   // method introduces patternWarnLatex in ant 
3424   public PatternWarnLatex createPatternWarnLatex() {
3425     return new PatternWarnLatex();
3426   }
3427 
3428   // defines patternWarnLatex element with text in ant 
3429   public class PatternWarnLatex {
3430     // FIXME: this is without property resolution. 
3431     // to add this need  pattern = getProject().replaceProperties(pattern)
3432     // with Task.getProject() 
3433     public void addText(String pattern) {
3434       Settings.this.setPatternWarnLatex(pattern);
3435     }
3436   }
3437 
3438   public void setDebugBadBoxes(boolean debugBadBoxes) {
3439     this.debugBadBoxes = debugBadBoxes;
3440   }
3441 
3442   public void setDebugWarnings(boolean debugWarnings) {
3443     this.debugWarnings = debugWarnings;
3444   }
3445 
3446   public void setPdfViaDvi(boolean pdfViaDvi) {
3447     this.pdfViaDvi = pdfViaDvi;
3448   }
3449 
3450   public void setDvi2pdfCommand(String dvi2pdfCommand) {
3451     this.dvi2pdfCommand = dvi2pdfCommand;
3452   }
3453 
3454   public void setDvi2pdfOptions(String dvi2pdfOptions) {
3455     this.dvi2pdfOptions = dvi2pdfOptions.replaceAll("(\t|\n| )+", " ").trim();
3456   }
3457 
3458   // setter method for patternReRunLatex in maven 
3459   public void setPatternReRunLatex(String patternReRunLatex) {
3460     this.patternReRunLatex =
3461         patternReRunLatex.replaceAll("(\t|\n)+", "").trim();
3462   }
3463 
3464   // method introduces patternReRunLatex in ant 
3465   public PatternReRunLatex createPatternReRunLatex() {
3466     return new PatternReRunLatex();
3467   }
3468 
3469   // defines patternNeedAnotherLatexRun element with text in ant 
3470   public class PatternReRunLatex {
3471     // FIXME: this is without property resolution. 
3472     // to add this need  pattern = getProject().replaceProperties(pattern)
3473     // with Task.getProject() 
3474     public void addText(String pattern) {
3475       Settings.this.setPatternReRunLatex(pattern);
3476     }
3477   }
3478 
3479   // FIXME: real check needed. also in other locations. 
3480   public void setMaxNumReRunsLatex(int maxNumReRunsLatex) {
3481     assert maxNumReRunsLatex >= 1
3482         || maxNumReRunsLatex == -1 : "Found illegal max number of reruns "
3483             + maxNumReRunsLatex + ". ";
3484     this.maxNumReRunsLatex = maxNumReRunsLatex;
3485   }
3486 
3487   public void setBibtexCommand(String bibtexCommand) {
3488     this.bibtexCommand = bibtexCommand;
3489   }
3490 
3491   public void setBibtexOptions(String bibtexOptions) {
3492     this.bibtexOptions = beautifyOptions(bibtexOptions);
3493   }
3494 
3495   // setter method for patternErrBibtex in maven 
3496   public void setPatternErrBibtex(String patternErrBibtex) {
3497     this.patternErrBibtex = patternErrBibtex;
3498   }
3499 
3500   // method introduces patternErrBibtex in ant 
3501   public PatternErrBibtex createPatternErrBibtex() {
3502     return new PatternErrBibtex();
3503   }
3504 
3505   // defines patternErrBibtex element with text in ant 
3506   public class PatternErrBibtex {
3507     // FIXME: this is without property resolution. 
3508     // to add this need  pattern = getProject().replaceProperties(pattern)
3509     // with Task.getProject() 
3510     public void addText(String pattern) {
3511       Settings.this.setPatternErrBibtex(pattern);
3512     }
3513   }
3514 
3515   // setter method for patternWarnBibtex in maven 
3516   public void setPatternWarnBibtex(String patternWarnBibtex) {
3517     this.patternWarnBibtex = patternWarnBibtex;
3518   }
3519 
3520   // method introduces patternWarnBibtex in ant 
3521   public PatternWarnBibtex createPatternWarnBibtex() {
3522     return new PatternWarnBibtex();
3523   }
3524 
3525   // defines patternWarnBibtex element with text in ant 
3526   public class PatternWarnBibtex {
3527     // FIXME: this is without property resolution. 
3528     // to add this need  pattern = getProject().replaceProperties(pattern)
3529     // with Task.getProject() 
3530     public void addText(String pattern) {
3531       Settings.this.setPatternWarnBibtex(pattern);
3532     }
3533   }
3534 
3535   // for indices 
3536 
3537   public void setPatternMultiIndex(String patternMultiIndex) {
3538     this.patternMultiIndex = patternMultiIndex;
3539   }
3540 
3541   public void setMakeIndexCommand(String makeIndexCommand) {
3542     this.makeIndexCommand = makeIndexCommand;
3543   }
3544 
3545   public void setMakeIndexOptions(String makeIndexOptions) {
3546     this.makeIndexOptions = beautifyOptions(makeIndexOptions);
3547   }
3548 
3549   // setter method for patternErrMakeIndex in maven 
3550   public void setPatternErrMakeIndex(String patternErrMakeIndex) {
3551     this.patternErrMakeIndex = patternErrMakeIndex.replaceAll("\n+", "").trim();
3552   }
3553 
3554   // method introduces patternErrMakeIndex in ant 
3555   public PatternErrMakeIndex createPatternErrMakeIndex() {
3556     return new PatternErrMakeIndex();
3557   }
3558 
3559   // defines patternErrMakeIndex element with text in ant 
3560   public class PatternErrMakeIndex {
3561     // FIXME: this is without property resolution. 
3562     // to add this need  pattern = getProject().replaceProperties(pattern)
3563     // with Task.getProject() 
3564     public void addText(String pattern) {
3565       Settings.this.setPatternErrMakeIndex(pattern);
3566     }
3567   }
3568 
3569   // FIXME: MakeIndex
3570   // setter method for patternWarnMakeIndex in maven 
3571   public void setPatternWarnMakeIndex(String patternWarnMakeIndex) {
3572     this.patternWarnMakeIndex =
3573         patternWarnMakeIndex.replaceAll("\n+", "").trim();
3574   }
3575 
3576   // method introduces patternWarnMakeIndex in ant 
3577   public PatternWarnMakeIndex createPatternWarnMakeIndex() {
3578     return new PatternWarnMakeIndex();
3579   }
3580 
3581   // defines patternWarnMakeIndex element with text in ant 
3582   public class PatternWarnMakeIndex {
3583     // FIXME: this is without property resolution. 
3584     // to add this need  pattern = getProject().replaceProperties(pattern)
3585     // with Task.getProject() 
3586     public void addText(String pattern) {
3587       Settings.this.setPatternWarnMakeIndex(pattern);
3588     }
3589   }
3590 
3591 
3592   public void setSplitIndexCommand(String splitIndexCommand) {
3593     this.splitIndexCommand = splitIndexCommand;
3594   }
3595 
3596   public void setSplitIndexOptions(String splitIndexOptions) {
3597     this.splitIndexOptions = beautifyOptions(splitIndexOptions);
3598   }
3599 
3600   public void setMakeGlossariesCommand(String makeGlossariesCommand) {
3601     this.makeGlossariesCommand = makeGlossariesCommand;
3602   }
3603 
3604   public void setMakeGlossariesOptions(String makeGlossariesOptions) {
3605     this.makeGlossariesOptions = beautifyOptions(makeGlossariesOptions);
3606   }
3607 
3608   public void setPatternWarnXindy(String patternWarnXindy) {
3609     this.patternWarnXindy = patternWarnXindy.replaceAll("\n+", "").trim();
3610   }
3611 
3612   public void setPatternErrXindy(String patternErrXindy) {
3613     this.patternErrXindy = patternErrXindy.replaceAll("\n+", "").trim();
3614   }
3615 
3616   public void setPythontexCommand(String pythontexCommand) {
3617     this.pythontexCommand = pythontexCommand;
3618   }
3619 
3620   public void setPythontexOptions(String pythontexOptions) {
3621     this.pythontexOptions = beautifyOptions(pythontexOptions);
3622   }
3623 
3624   public void setPatternErrPyTex(String patternErrPyTex) {
3625     this.patternErrPyTex = patternErrPyTex.replaceAll("(\t|\n| )+", " ").trim();
3626   }
3627 
3628   public void setPatternWarnPyTex(String patternWarnPyTex) {
3629     this.patternWarnPyTex =
3630         patternWarnPyTex.replaceAll("(\t|\n| )+", " ").trim();
3631   }
3632 
3633   public void setPrefixPytexOutFolder(String prefixPytexOutFolder) {
3634     this.prefixPytexOutFolder = prefixPytexOutFolder;
3635   }
3636 
3637 
3638   public void setTex4htCommand(String tex4htCommand) {
3639     this.tex4htCommand = tex4htCommand;
3640   }
3641 
3642   public void setTex4htStyOptions(String tex4htStyOptions) {
3643     this.tex4htStyOptions = beautifyOptions(tex4htStyOptions);
3644   }
3645 
3646   public void setTex4htOptions(String tex4htOptions) {
3647     this.tex4htOptions = tex4htOptions.replaceAll("(\t|\n| )+", " ").trim();
3648   }
3649 
3650   public void setT4htOptions(String t4htOptions) {
3651     this.t4htOptions = beautifyOptions(t4htOptions);
3652   }
3653 
3654   // setter method for patternT4htOutputFiles in maven 
3655   public void setPatternT4htOutputFiles(String patternT4htOutputFiles) {
3656     this.patternT4htOutputFiles =
3657         patternT4htOutputFiles.replaceAll("(\t|\n| )+", "").trim();
3658   }
3659 
3660   // method introduces patternT4htOutputFiles in ant 
3661   public PatternT4htOutputFiles createPatternT4htOutputFiles() {
3662     return new PatternT4htOutputFiles();
3663   }
3664 
3665   // defines patternT4htOutputFiles element with text in ant 
3666   public class PatternT4htOutputFiles {
3667     // FIXME: this is without property resolution. 
3668     // to add this need  pattern = getProject().replaceProperties(pattern)
3669     // with Task.getProject() 
3670     public void addText(String pattern) {
3671       Settings.this.setPatternT4htOutputFiles(pattern);
3672     }
3673   }
3674 
3675   public void setLatex2rtfCommand(String latex2rtfCommand) {
3676     this.latex2rtfCommand = latex2rtfCommand;
3677   }
3678 
3679   // FIXME: replaceAll: should be unified. 
3680   public void setLatex2rtfOptions(String latex2rtfOptions) {
3681     this.latex2rtfOptions = beautifyOptions(latex2rtfOptions);
3682   }
3683 
3684   public void setOdt2docCommand(String odt2docCommand) {
3685     this.odt2docCommand = odt2docCommand;
3686   }
3687 
3688   public void setOdt2docOptions(String odt2docOptions) {
3689     this.odt2docOptions = beautifyOptions(odt2docOptions);
3690   }
3691 
3692   public void setPdf2txtCommand(String pdf2txtCommand) {
3693     this.pdf2txtCommand = pdf2txtCommand;
3694   }
3695 
3696   // getter commands: for ant task only. 
3697   public void setPdf2txtOptions(String pdf2txtOptions) {
3698     this.pdf2txtOptions = beautifyOptions(pdf2txtOptions);
3699   }
3700 
3701   public void setChkTexCommand(String chkTexCommand) {
3702     this.chkTexCommand = chkTexCommand;
3703   }
3704 
3705   public void setChkTexOptions(String chkTexOptions) {
3706     this.chkTexOptions = beautifyOptions(chkTexOptions);
3707   }
3708 
3709   public void setVerifyStdCommand(String verifyStdCommand) {
3710     this.verifyStdCommand = verifyStdCommand;
3711   }
3712 
3713   public void setVerifyStdOptions(String verifyStdOptions) {
3714     this.verifyStdOptions = beautifyOptions(verifyStdOptions);
3715   }
3716 
3717   public void setVerifyByCmp(boolean verifyByCmp) {
3718     this.verifyByCmp = verifyByCmp;;
3719   }
3720 
3721   public void setDiffPdfCommand(String diffPdfCommand) {
3722     this.diffPdfCommand = diffPdfCommand;
3723   }
3724 
3725   public void setPdfMetainfoCommand(String pdfMetainfoCommand) {
3726     this.pdfMetainfoCommand = pdfMetainfoCommand;
3727   }
3728 
3729   public void setPdfMetainfoOptions(String pdfMetainfoOptions) {
3730     this.pdfMetainfoOptions = beautifyOptions(pdfMetainfoOptions);
3731   }
3732 
3733   public void setPdfMetainfoXmpOptions(String pdfMetainfoXmpOptions) {
3734     this.pdfMetainfoXmpOptions = beautifyOptions(pdfMetainfoXmpOptions);
3735   }
3736 
3737   public void setLatexmkCommand(String latexmkCommand) {
3738     this.latexmkCommand = latexmkCommand;
3739   }
3740 
3741   public void setLatexmkOptions(String latexmkOptions) {
3742     this.latexmkOptions = beautifyOptions(latexmkOptions);
3743   }
3744 
3745   /**
3746    * Returns the parameters defined in this class as a map from their names to their values. 
3747    * Parameters are marked by annotations of type {@link Parameter}. 
3748    * Since this is not runtime visible, we mark parameters with another annotation, {@link RuntimeParameter}. 
3749    * Currently, their names are the names of the field (TBD: add check, see changes). 
3750    * There is one case where the default value is <code>null</code>. 
3751    * The string representation is 'null'. 
3752    * In the long run, the {@link RuntimeParameter} shall be added automatically 
3753    * while performing check of names. 
3754    * Currently it is checked that the parameter is private and not static. 
3755    * 
3756    * The ordering of the parameters in the returned map 
3757    * is the ordering of the according fields in the class. 
3758    * To that end, we use {@link LinkedHashMap}. 
3759    * This is important when using this method for the {@link #toString()} method. 
3760    * 
3761    * @return
3762    *   A map from names of parameters to their current values as a string. 
3763    *   If <code>null</code> use the string 'null'. 
3764    *   Order is as fields are declared. 
3765    */
3766   public Map<String, String> getProperties() {
3767     // keys are never null, but values may be null 
3768     Map<String, String> res = new LinkedHashMap<String, String>();
3769     Field[] fields = this.getClass().getDeclaredFields();
3770     String name;
3771     Object value;
3772     int mod;
3773     for (Field field : fields) {
3774       // TBD: in the long run maybe Parameter
3775       RuntimeParameter annot = field.getAnnotation(RuntimeParameter.class);
3776       //System.out.println(Arrays.asList(field.getDeclaredAnnotations()));
3777       if (annot == null) {
3778         // Here, the field is no parameter. 
3779         continue;
3780       }
3781       // Here, the field is a parameter 
3782       // TBD: check for right name and default value 
3783       mod = field.getModifiers();
3784       if (Modifier.isStatic(mod)) {
3785         continue;
3786       }
3787       assert !Modifier.isStatic(mod) : "found static parameter " + field + ". ";
3788       assert !Modifier.isFinal(mod) : "found final parameter " + field + ". ";
3789       assert Modifier.isPrivate(mod) : "found non-private parameter " + field + ". ";
3790 
3791       name = field.getName();
3792       //assert annot.name().equals(name) : "Parameter name shall be fieldname. ";
3793       field.setAccessible(true);
3794       try {
3795         value = field.get(this);
3796         res.put(name, value == null ? null : value.toString());
3797       } catch (IllegalArgumentException iare) {
3798         throw new IllegalStateException(
3799             "Found no field '" + name + "' in setting. ");
3800       } catch (IllegalAccessException iace) {
3801         throw new IllegalStateException(
3802             "Illegal access to field '" + name + "' although set accessible. ");
3803       }
3804     } // for 
3805     return res;
3806   }
3807 
3808   /**
3809    * Returns the getter methods defined in this class used for injection
3810    * as a map from their names to their return values. 
3811    * Getter methods, i.e. methods without parameters, 
3812    * are marked by annotations of type {@link Parameter}. 
3813    * Since this is not runtime visible, 
3814    * we mark parameters with another annotation, {@link RuntimeParameter}. 
3815    * Currently, their names are the names of the methods. 
3816    * There is one case where the default value is <code>null</code>. 
3817    * The string representation is 'null'. 
3818    * In the long run, the {@link RuntimeParameter} shall be added automatically 
3819    * while performing check of names. 
3820    * Currently it is checked that the method has no parameters and not static. 
3821    * 
3822    * The ordering of the getter methods in the returned map 
3823    * is the ordering of the according methods in the class. 
3824    * To that end, we use {@link LinkedHashMap}. 
3825    * 
3826    * @return
3827    *   A map from names of methods to their current return values as a string. 
3828    *   If <code>null</code> use the string 'null'. 
3829    *   Ordering is as methods are declared. 
3830    */
3831   // some potential in unification: Member unifying Field and Method 
3832   public Map<String, String> getMethodsNoParams() {
3833     Map<String, String> res = new LinkedHashMap<String, String>();
3834     Method[] methods = this.getClass().getDeclaredMethods();//.getMethods();
3835     String name;
3836     Object value;
3837     int mod;
3838     for (Method method : methods) {
3839       RuntimeParameter annot = method.getAnnotation(RuntimeParameter.class);
3840       if (annot == null) {
3841         // Here, the field is no parameter. 
3842         continue;
3843       }
3844       mod = method.getModifiers();
3845       assert method.getParameterTypes().length == 0 : "found getter with parameter. ";
3846       assert !Modifier.isStatic(mod) : "found static getter. ";
3847 
3848       name = method.getName();
3849       method.setAccessible(true);
3850 
3851       try {
3852         value = method.invoke(this);
3853         res.put(name, value == null ? null : value.toString());
3854       } catch (IllegalArgumentException iare) {
3855         throw new IllegalStateException(
3856             "Found no method '" + name + "()' in setting. ");
3857       } catch (IllegalAccessException iace) {
3858         throw new IllegalStateException(
3859             "Illegal access to method '" + name + "' although set accessible. ");
3860       } catch (InvocationTargetException ite) {
3861         throw new IllegalStateException(
3862             "Invocation of method '" + name + "()' caused exception. ", ite);
3863       }
3864     } // for 
3865 
3866     return res;
3867   }
3868 
3869   /**
3870    * Returns the file associated with the resource <code>fileNameResource</code>. 
3871    *
3872    * @param fileNameResource
3873    *   The name of the resource which is also the (short) file name returned. 
3874    * @return
3875    *   the file in directory {@link #texSrcDirectory} or in the local directory 
3876    *   with name <code>fileNameResource</code>. 
3877    *   The directory is the local one 
3878    *   if injection is invoked by property named {@link #PARAM_PROP}, 
3879    *   else it is {@link #texSrcDirectory}. 
3880    */
3881   File rcResourceToFile(String fileNameResource) {
3882     String dir = (System.getProperty(PARAM_PROP) == null) ? this.texSrcDirectory : ".";
3883     return new File(dir, fileNameResource);
3884   }
3885 
3886   /**
3887    * Filters a resource given by <code>inStream</code> 
3888    * into a <code>writer</code> similar to the maven resources plugin: 
3889    * Replace the settings given by name in the form <code>${&lt;name%gt;}</code> 
3890    * by the current value of the setting with the given name. 
3891    * In contrast to the resources plugin, 
3892    * the names refer to settings not to parameters, e.g. given in the pom. 
3893    * <p>
3894    * This is applied e.g. to record files, 
3895    * <code>.latexmkrc</code> and <code>.chktexrc</code>. 
3896    * That way, <code>latexmk</code> and <code>chktex</code> 
3897    * run with the according configuration 
3898    * are aligned with the current settings of this plugin. 
3899    *
3900    * @param inStream
3901    *   The stream of the file to be filtered. 
3902    *   This refers to the source file which is loaded 
3903    *   as a resource with a certain filename. 
3904    * @param writer
3905    *   Refers to the file in folder 
3906    *   given by the parameter {@link #texSrcDirectory} 
3907    *   with the same name as the resource defining <code>inStream</code>. 
3908    * @param version
3909    *   the version of this software going into the headline.
3910    * @param inj
3911    *   The injection which determines the comment indentifier 
3912    *   and whether there is a hashbanb. 
3913    * @throws IOException
3914    *   May occur if reading a line but not if writing a line. 
3915    */
3916   public void filterInjection(InputStream inStream,
3917                               PrintStream writer,
3918                               String version,
3919                               Injection inj) throws IOException {//
3920     BufferedReader bufReader =
3921         new BufferedReader(new InputStreamReader(inStream));
3922 
3923     // pattern for parameter 
3924     Pattern pattern = Pattern.compile(PATTERN_CONFIG);
3925     Map<String, String> props = this.getProperties();
3926     Map<String, String> getters = this.getMethodsNoParams();
3927 
3928     String strLine;
3929     if (inj.hasShebang()) {
3930       strLine = bufReader.readLine();
3931       // this is because strLine is the shebang line. 
3932       assert strLine != null;
3933       // write shebang line as is 
3934       writer.println(strLine);
3935     }
3936     // the headline shows that the file is generated 
3937     // and may thus be overwritten and erased. 
3938     // throws IOExeption if an IO error occurs 
3939     writer.println(inj.commentStr() + TexFileUtils.HEADLINE_GEN + version);
3940 
3941     // Read File Line By Line
3942     Matcher matcher;
3943     String replacement;
3944 
3945     // throws IOExeption if an IO error occurs
3946     while ((strLine = bufReader.readLine()) != null) {
3947       // filter until no variable in strLine found 
3948       while (true) {
3949         matcher = pattern.matcher(strLine);
3950         if (!matcher.find()) {
3951           // Here, no variable in strLine found 
3952           writer.println(strLine);
3953           break;
3954         }
3955         assert matcher.groupCount() >= 1;
3956 
3957         // group zero is the whole, and it is not in the goup count 
3958         // System.out.println("line: |"+strLine+"|");
3959         // System.out.println("key: |"+matcher.group(GRP_NAME)+"|");
3960         // System.out.println("val: |"+props.get(matcher.group(GRP_NAME))+"|");
3961         if (matcher.group(GRP_METHOD) == null) {
3962           // Here, we have the content of a field 
3963           assert props.containsKey(matcher.group(GRP_NAME)) : "Key '"
3964               + matcher.group(GRP_NAME) + "' not found. ";
3965           replacement = props.get(matcher.group(GRP_NAME));
3966         } else {
3967           // Here, we have the result of a getter method 
3968           assert getters.containsKey(matcher.group(GRP_NAME)) : "Key '"
3969               + matcher.group(GRP_NAME) + "' not found. ";
3970           replacement = getters.get(matcher.group(GRP_NAME));
3971         }
3972   
3973         // TBD: Essentially, this is only appropriate for injection of .latexmkrc 
3974         // Here also goes into that java escape and perl escape are the same. 
3975         // What is needed is treatment depending on the language of the injection. 
3976         // To that end, the language must be implemented as an enum. 
3977         // the comment character tied to the injection directly, 
3978         // must be tied to the language which is tied to the injection. 
3979         replacement = StringEscapeUtils.escapeJava(replacement)
3980         .replace("\\",  "\\\\")
3981         .replace("$",  "\\$");
3982 
3983         strLine = matcher.replaceFirst(replacement);
3984         // filter next line 
3985       } // while true
3986     } // while ((strLine = bufReader.readLine()) != null)
3987 
3988     // flush and close the streams 
3989     writer.flush();
3990     writer.close();
3991   }
3992 
3993   public String toString() {
3994     List<String> res = new ArrayList<String>();
3995     //String name, value;
3996     // name = "baseDirectory";
3997     // value = this.baseDirectory.toString();
3998     // res.add(name + "=" + value + "");
3999     // name = "targetDirectory";
4000     // value = this.targetDirectory.toString();
4001     // res.add(name + "=" + value + "");
4002     // name = "targetSiteDirectory";
4003     // value = this.targetSiteDirectory.toString();
4004     // res.add(name + "=" + value + "");
4005     Map<String, String> name2value = this.getProperties();
4006 
4007     for (Map.Entry<String, String> entry : name2value.entrySet()) {
4008       res.add(entry.getKey() + "='" + entry.getValue() + "'");
4009     }
4010     return res.toString();
4011   }
4012 
4013   public static void main(String[] args) {
4014     System.out.println("texpath: " + new Settings().getTexPath());
4015   }
4016 }