1 package eu.simuline.m2latex.core;
2
3 import java.io.File;
4 import java.util.Arrays;
5
6 /**
7 * Describe class AbstractLatexProcessor here.
8 *
9 *
10 * Created: Thu Nov 17 12:29:36 2016
11 *
12 * @author <a href="mailto:rei3ner@arcor.de">Ernst Reissner</a>
13 * @version 1.0
14 */
15 abstract class AbstractLatexProcessor {
16
17 // both LatexProcessor and LatexPreProcessor
18 // LaTeX and mpost with option -recorder
19 final static String SUFFIX_FLS = ".fls";
20 // both LatexProcessor and LatexPreProcessor
21 // for LaTeX but also for mpost
22 final static String SUFFIX_LOG = ".log";
23
24 // both LatexProcessor and LatexPreProcessor
25 final static String SUFFIX_PDF = ".pdf";
26
27 // makeindex for glossary
28 // needed by makeglossaries and for svg-conversion (hack)
29 final static String SUFFIX_VOID = "";
30
31 // both LatexProcessor and LatexPreProcessor
32 protected final Settings settings;
33
34 // both LatexProcessor and LatexPreProcessor
35 protected final CommandExecutor executor;
36
37 // both LatexProcessor and LatexPreProcessor
38 protected final LogWrapper log;
39
40 // both LatexProcessor and LatexPreProcessor
41 protected final TexFileUtils fileUtils;
42
43 /**
44 * Creates a new <code>AbstractLatexProcessor</code> instance.
45 *
46 */
47 public AbstractLatexProcessor(Settings settings,
48 CommandExecutor executor,
49 LogWrapper log,
50 TexFileUtils fileUtils) {
51 this.settings = settings;
52 this.log = log;
53 this.executor = executor;
54 this.fileUtils = fileUtils;
55 }
56
57 /**
58 * Logs if an error occurred running <code>command</code>
59 * by detecting that the log file <code>logFile</code> has not been created
60 * or by detecting the error pattern <code>pattern</code>
61 * in <code>logFile</code>.
62 * <p>
63 * Logging:
64 * <ul>
65 * <li> EAP01 Running <code>command</code> failed. For details...
66 * <li> EAP02 Running <code>command</code> failed. No log file
67 * <li> WAP04 if <code>logFile</code> is not readable.
68 * <li> WFU03 cannot close
69 * </ul>
70 * @see #logWarns(File, String, String)
71 */
72 protected void logErrs(File logFile, String command, String pattern) {
73 if (logFile.exists()) {
74 // hasErrsWarns may log warnings WFU03, WAP04
75 if (hasErrsWarns(logFile, pattern)) {
76 this.log.error("EAP01: Running " + command +
77 " failed. Errors logged in '" +
78 logFile.getName() + "'. ");
79 }
80 } else {
81 this.log.error("EAP02: Running " + command +
82 " failed: No log file '" +
83 logFile.getName() + "' written. ");
84 }
85 }
86
87 /**
88 * Logs if a warning occurred running <code>command</code>
89 * by detecting the warning pattern <code>pattern</code>
90 * in <code>logFile</code>.
91 * If <code>logFile</code> then an error occurred
92 * making detection of warnings obsolete.
93 * <p>
94 * Logging:
95 * <ul>
96 * <li> WAP03 Running <code>command</code> emitted warnings.
97 * <li> WAP04 if <code>logFile</code> is not readable.
98 * <li> WFU03 cannot close
99 * </ul>
100 *
101 * @see #logErrs(File, String, String)
102 */
103 // for both LatexProcessor and LatexPreProcessor
104 // FIXME: for LatexPreProcessor never needed.
105 protected void logWarns(File logFile, String command, String pattern) {
106 // hasErrsWarns may log warnings WFU03, WAP04
107 if (logFile.exists() && hasErrsWarns(logFile, pattern)) {
108 // logs warning WAP03: emitted warnings
109 logWarn(logFile, command);
110 }
111 }
112
113 /**
114 * <p>
115 * Logging:
116 * WAP03 Running <code>command</code> emitted warnings.
117 */
118 // invoked by logWarns(File, String, String) and
119 // LatexProcessor.logWarns(File, String)
120 protected void logWarn(File logFile, String command) {
121 this.log.warn("WAP03: Running " + command +
122 " emitted warnings logged in '" +
123 logFile.getName() + "'. ");
124 }
125
126 /**
127 *
128 * Logging:
129 * <ul>
130 * <li> WFU03 cannot close
131 * <li> WAP04 if <code>logFile</code> is not readable.
132 * </ul>
133 */
134 // FIXME: not clear whether error or warning; also command not clear.
135 // used in
136 // logErrs (File, String, String)
137 // logWarns(File, String, String)
138 protected boolean hasErrsWarns(File logFile, String pattern) {
139 assert logFile.exists() && !logFile.isDirectory()
140 : "Expected existing (regular) log file "+logFile;
141 // may log warning WFU03 cannot close
142 Boolean res = this.fileUtils.matchInFile(logFile, pattern);
143 if (res == null) {
144 this.log.warn("WAP04: Cannot read log file '" + logFile.getName() +
145 "'; may hide warnings/errors. ");
146 return false;
147 }
148 return res;
149 }
150
151 // for both LatexProcessor and LatexPreProcessor
152 protected boolean update(File source, File target) {
153 if (!target.exists()) {
154 return true;
155 }
156 assert source.exists() && !source.isDirectory()
157 : "Expected existing (regular) source "+source;
158
159 return source.lastModified() > target.lastModified();
160 }
161
162 /**
163 * Returns an array of strings,
164 * each entry with a single option given by <code>options</code>
165 * except the last one which is the name of <code>file</code>.
166 *
167 * @param options
168 * the options string. The individual options
169 * are expected to be separated by a single blank.
170 * @param file
171 * the file argument
172 * @return
173 * An array of strings:
174 * The 0th entry is the file name,
175 * The others, if <code>options</code> is not empty,
176 * are the options in <code>options</code>.
177 */
178 // for both LatexProcessor and LatexPreProcessor
179 // and in tests
180 protected static String[] buildArguments(String options, File file) {
181 if (options.isEmpty()) {
182 return new String[] {file.getName()};
183 }
184 String[] optionsArr = options.split(" ");
185 String[] args = Arrays.copyOf(optionsArr, optionsArr.length + 1);
186 args[optionsArr.length] = file.getName();
187
188 return args;
189 }
190 }