1 | /**
|
---|
2 | *#########################################################################
|
---|
3 | *
|
---|
4 | * A component of the Gatherer application, part of the Greenstone digital
|
---|
5 | * library suite from the New Zealand Digital Library Project at the
|
---|
6 | * University of Waikato, New Zealand.
|
---|
7 | *
|
---|
8 | * <BR><BR>
|
---|
9 | *
|
---|
10 | * Author: John Thompson, Greenstone Digital Library, University of Waikato
|
---|
11 | *
|
---|
12 | * <BR><BR>
|
---|
13 | *
|
---|
14 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
15 | *
|
---|
16 | * <BR><BR>
|
---|
17 | *
|
---|
18 | * This program is free software; you can redistribute it and/or modify
|
---|
19 | * it under the terms of the GNU General Public License as published by
|
---|
20 | * the Free Software Foundation; either version 2 of the License, or
|
---|
21 | * (at your option) any later version.
|
---|
22 | *
|
---|
23 | * <BR><BR>
|
---|
24 | *
|
---|
25 | * This program is distributed in the hope that it will be useful,
|
---|
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
28 | * GNU General Public License for more details.
|
---|
29 | *
|
---|
30 | * <BR><BR>
|
---|
31 | *
|
---|
32 | * You should have received a copy of the GNU General Public License
|
---|
33 | * along with this program; if not, write to the Free Software
|
---|
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
35 | *########################################################################
|
---|
36 | */
|
---|
37 |
|
---|
38 |
|
---|
39 |
|
---|
40 |
|
---|
41 |
|
---|
42 |
|
---|
43 | package org.greenstone.gatherer.util;
|
---|
44 |
|
---|
45 | import java.io.BufferedReader;
|
---|
46 | import java.io.File;
|
---|
47 | import java.io.FileOutputStream;
|
---|
48 | import java.io.FileReader;
|
---|
49 | import java.lang.Exception;
|
---|
50 | import java.lang.String;
|
---|
51 | import java.lang.StringBuffer;
|
---|
52 | import java.util.HashMap;
|
---|
53 | /** Automatically generates html help documents given an input text file using markup and a template defining what the markup means.
|
---|
54 | * @author John Thompson, Greenstone Digital Library, University of Waikato
|
---|
55 | * @version 1.0
|
---|
56 | */
|
---|
57 | public class Generator {
|
---|
58 |
|
---|
59 | private FileOutputStream file_output_stream = null;
|
---|
60 |
|
---|
61 | private TemplateManager template_manager = null;
|
---|
62 |
|
---|
63 | public Generator(File test_file, File template_file) {
|
---|
64 | template_manager = new TemplateManager(template_file);
|
---|
65 | File files[] = null;
|
---|
66 | // If test_file is a file, goody.
|
---|
67 | if(test_file.isFile()) {
|
---|
68 | files = new File[1];
|
---|
69 | files[0] = test_file;
|
---|
70 | }
|
---|
71 | // Otherwise we use all of test_files children.
|
---|
72 | else {
|
---|
73 | files = test_file.listFiles();
|
---|
74 | }
|
---|
75 | // Its unfortunate we test this twice for the basic case, but we need to ensure that source managers are only contructed for non-directory files.
|
---|
76 | for(int i = 0; i < files.length; i++) {
|
---|
77 | if(files[i].isFile()) {
|
---|
78 | SourceManager source_manager = new SourceManager(files[i]);
|
---|
79 | source_manager = null;
|
---|
80 | }
|
---|
81 | }
|
---|
82 | // All done.
|
---|
83 | }
|
---|
84 |
|
---|
85 | public void exit() {
|
---|
86 | if(file_output_stream != null) {
|
---|
87 | try {
|
---|
88 | file_output_stream.close();
|
---|
89 | file_output_stream = null;
|
---|
90 | }
|
---|
91 | catch(Exception error) {
|
---|
92 | error.printStackTrace();
|
---|
93 | }
|
---|
94 | }
|
---|
95 | System.exit(0);
|
---|
96 | }
|
---|
97 |
|
---|
98 | public void out(String msg) {
|
---|
99 | System.err.println(msg);
|
---|
100 | try {
|
---|
101 | if(file_output_stream == null) {
|
---|
102 | file_output_stream = new FileOutputStream("output.txt");
|
---|
103 | }
|
---|
104 | file_output_stream.write((msg + "\n").getBytes());
|
---|
105 | }
|
---|
106 | catch(Exception error) {
|
---|
107 | error.printStackTrace();
|
---|
108 | System.err.println("An error has occured. View output.txt for more information.");
|
---|
109 | exit();
|
---|
110 | }
|
---|
111 | }
|
---|
112 |
|
---|
113 | static public void main(String args[]) {
|
---|
114 | System.err.println("Rapid repeated HTML generation tool.");
|
---|
115 | System.err.println(" written by John Thompson, 2002\n");
|
---|
116 | boolean usage = false;
|
---|
117 | // Attempt to generate html from text
|
---|
118 | if(args.length == 2) {
|
---|
119 | File text_file = new File(args[0]);
|
---|
120 | File template_file = new File(args[1]);
|
---|
121 | if(!text_file.exists() || !template_file.exists() || !template_file.isFile()) {
|
---|
122 | usage = true;
|
---|
123 | }
|
---|
124 | else {
|
---|
125 | Generator generator = new Generator(text_file, template_file);
|
---|
126 | generator.exit();
|
---|
127 | }
|
---|
128 | }
|
---|
129 | else {
|
---|
130 | usage = true;
|
---|
131 | }
|
---|
132 | // Print usage message
|
---|
133 | if(usage) {
|
---|
134 | System.err.println("Usage: GenHelp <text_file> <template_file>");
|
---|
135 | System.err.println("text_file - A file containing text marked up using special tags.");
|
---|
136 | System.err.println("template_file - An HTML file using tags to specify where to insert text.");
|
---|
137 | }
|
---|
138 | }
|
---|
139 |
|
---|
140 | /** An HTML block object is essentially a String buffer containing several places where it demands further text be appended. To this end you can ask if an HTML block is ready, and if not provide it with a further text fragment and try again. */
|
---|
141 | private class HTMLBlock {
|
---|
142 | /** Prevent the original HTML block being changed. */
|
---|
143 | private boolean original;
|
---|
144 |
|
---|
145 | private int insertion_position = -1;
|
---|
146 | /** The name of this HTML block as taken from the template file. */
|
---|
147 | private String name = null;
|
---|
148 | private String paragraph_tag = null;
|
---|
149 | /** The HTML block itself. */
|
---|
150 | private StringBuffer data = null;
|
---|
151 | /** Constructor takes the HTML blocks name as extracted from the template file.
|
---|
152 | * @param name The name of this HTML block as a <strong>String</strong>.
|
---|
153 | */
|
---|
154 | public HTMLBlock(String name) {
|
---|
155 | this.data = new StringBuffer("");
|
---|
156 | this.name = name;
|
---|
157 | this.original = true;
|
---|
158 | }
|
---|
159 | /** Copy constructor takes the HTML block and its name as extracted from the template file.
|
---|
160 | * @param name The name of this HTML block as a <strong>String</strong>.
|
---|
161 | * @param raw The raw HTML code as a <strong>String</strong>.
|
---|
162 | */
|
---|
163 | public HTMLBlock(String name, String raw) {
|
---|
164 | this.data = new StringBuffer(raw);
|
---|
165 | this.name = name;
|
---|
166 | this.original = false;
|
---|
167 | }
|
---|
168 | /** Append this text to the end of the current block.
|
---|
169 | * @param text The <strong>String</strong> to add.
|
---|
170 | */
|
---|
171 | public void addLine(String text) {
|
---|
172 | if(original) {
|
---|
173 | data.append(text);
|
---|
174 | data.append("\n");
|
---|
175 | }
|
---|
176 | }
|
---|
177 | /** Retrieve the name of this HTML block.
|
---|
178 | * @return A <strong>String</strong> representing the name.
|
---|
179 | */
|
---|
180 | public String getName() {
|
---|
181 | return name;
|
---|
182 | }
|
---|
183 | /** Insert a text fragment into this HTML block.
|
---|
184 | * @param fragment The <strong>String</strong> to insert.
|
---|
185 | * @return <i>true</i> if an insertion occured, <i>false</i> otherwise.
|
---|
186 | */
|
---|
187 | public boolean insert(String fragment) {
|
---|
188 | if(!original) {
|
---|
189 | // Find the start of an insertion tag.
|
---|
190 | int start = data.indexOf("<$");
|
---|
191 | if(start != -1) {
|
---|
192 | // Find the end of an insertion tag.
|
---|
193 | int end = data.indexOf(">", start) + 1;
|
---|
194 | // Determine the tag, and search for any paragraphing information.
|
---|
195 | String tag = data.substring(start, end);
|
---|
196 | if(tag.length() > 7) {
|
---|
197 | paragraph_tag = "<p " + tag.substring(7) + "\n";
|
---|
198 | fragment = paragraph_tag + fragment + "\n</p>\n";
|
---|
199 | }
|
---|
200 | // Substitue the fragment for the tag.
|
---|
201 | data.replace(start, end, fragment);
|
---|
202 | // Now set insertion position
|
---|
203 | insertion_position = start + fragment.length();
|
---|
204 | return true;
|
---|
205 | }
|
---|
206 | // Its possible that we've already got enough text to output this block. Essentially this new fragment is meant to be another paragraph. Such fragments are always added immediately after the last fragment inserted.
|
---|
207 | else if(insertion_position != -1) {
|
---|
208 | if(paragraph_tag != null) {
|
---|
209 | fragment = paragraph_tag + fragment + "\n</p>\n";
|
---|
210 | }
|
---|
211 | data.insert(insertion_position, fragment);
|
---|
212 | insertion_position = insertion_position + fragment.length();
|
---|
213 | }
|
---|
214 | }
|
---|
215 | return false;
|
---|
216 | }
|
---|
217 | /** Is this block ready to written out.
|
---|
218 | * @return <i>true</i> if we can write this block out, <i>false</i> if text insertion points still exist.
|
---|
219 | */
|
---|
220 | public boolean ready() {
|
---|
221 | return data.indexOf("<$") == -1;
|
---|
222 | }
|
---|
223 | /** Produce a copy of this block with all text insertions intact.
|
---|
224 | * @return A new <strong>HTMLBlock</strong>.
|
---|
225 | */
|
---|
226 | public HTMLBlock spawn() {
|
---|
227 | return new HTMLBlock(name, data.toString());
|
---|
228 | }
|
---|
229 | /** Return the HTML block within this object.
|
---|
230 | * @return A <strong>String</strong> containing the HTML code.
|
---|
231 | */
|
---|
232 | public String toString() {
|
---|
233 | return data.toString();
|
---|
234 | }
|
---|
235 | }
|
---|
236 | /** Reads in the given text file, outputing HTML by utilizing HTML blocks stored in the TemplateManager. The manager understands one extra tag <$FILE name=<filename>> which is used to indicate the presence of several output files within one input file. If this tag is not found the default name for the output file is "<text_file_name>.htm". */
|
---|
237 | private class SourceManager {
|
---|
238 | private File text_file = null;
|
---|
239 |
|
---|
240 | private FileOutputStream output_file = null;
|
---|
241 |
|
---|
242 | public SourceManager(File text_file) {
|
---|
243 | out("Building Source Manager:");
|
---|
244 | this.text_file = text_file;
|
---|
245 | try {
|
---|
246 | out(" reading from: " + text_file.getName());
|
---|
247 | // Create input stream from the text file which we read a line at a time.
|
---|
248 | FileReader file_reader = new FileReader(text_file);
|
---|
249 | BufferedReader buffered_reader = new BufferedReader(file_reader);
|
---|
250 | HTMLBlock block = null;
|
---|
251 | String line = null;
|
---|
252 | StringBuffer paragraph = null;
|
---|
253 | while((line = buffered_reader.readLine()) != null) {
|
---|
254 | boolean done = false;
|
---|
255 | // What we do here depends on what state we are in and what tag or text we are reading.
|
---|
256 | // The first case to consider is a file open command tag. This tells us the next block of html should be written to a certain file.
|
---|
257 | if(line.startsWith("<$FILE")) {
|
---|
258 | // Close any existing output file.
|
---|
259 | if(output_file != null) {
|
---|
260 | // Write any existing block
|
---|
261 | if(block != null) {
|
---|
262 | if(paragraph != null) {
|
---|
263 | block.insert(paragraph.toString());
|
---|
264 | paragraph = null;
|
---|
265 | }
|
---|
266 | out(" write: " + block.getName());
|
---|
267 | output_file.write((block.toString()).getBytes());
|
---|
268 | block = null;
|
---|
269 | }
|
---|
270 | output_file.close();
|
---|
271 | output_file = null;
|
---|
272 | }
|
---|
273 | // Determine the new file name.
|
---|
274 | String name = line.substring(12, line.lastIndexOf(">"));
|
---|
275 | // Create new file.
|
---|
276 | output_file = new FileOutputStream(name);
|
---|
277 | // Dealt with
|
---|
278 | out(" writing to: " + name);
|
---|
279 | name = null;
|
---|
280 | done = true;
|
---|
281 | }
|
---|
282 | else if(line.startsWith("<$")) {
|
---|
283 | // If we have a block open its time to write it out.
|
---|
284 | if(block != null) {
|
---|
285 | if(paragraph != null) {
|
---|
286 | block.insert(paragraph.toString());
|
---|
287 | paragraph = null;
|
---|
288 | }
|
---|
289 | // Check we have somewhere to write to.
|
---|
290 | if(output_file == null) {
|
---|
291 | output_file = new FileOutputStream(text_file.getName() + ".htm");
|
---|
292 | }
|
---|
293 | out(" write: " + block.getName());
|
---|
294 | output_file.write((block.toString()).getBytes());
|
---|
295 | block = null;
|
---|
296 | }
|
---|
297 | // Now determine the new blocks name.
|
---|
298 | String name = line.substring(2, line.lastIndexOf(">"));
|
---|
299 | // Retrieve that block
|
---|
300 | block = template_manager.getHTMLBlock(name);
|
---|
301 | if(block == null) {
|
---|
302 | // Somethings gone wrong, most likely an unidentified block name.
|
---|
303 | out(" no such block: " + name);
|
---|
304 | }
|
---|
305 | name = null;
|
---|
306 | done = true;
|
---|
307 | }
|
---|
308 | // Its just text. However we want text in paragraph blocks. A paragraph is delimited by a "\n\n" or the start of a tag.
|
---|
309 | if(!done) {
|
---|
310 | // If the line read is "" it means we've encountered a "\n\n".
|
---|
311 | if(line.equals("")) {
|
---|
312 | // Add paragraph to open block.
|
---|
313 | if(block != null && paragraph != null) {
|
---|
314 | block.insert(paragraph.toString());
|
---|
315 | paragraph = null;
|
---|
316 | }
|
---|
317 | }
|
---|
318 | // Any other case just add to paragraph. Ensure that there is at least one space between the two fragments
|
---|
319 | else {
|
---|
320 | if(paragraph == null) {
|
---|
321 | paragraph = new StringBuffer(line);
|
---|
322 | }
|
---|
323 | else {
|
---|
324 | if(paragraph.charAt(paragraph.length() - 1) != ' ' && line.charAt(0) != ' ') {
|
---|
325 | paragraph.append(" ");
|
---|
326 | }
|
---|
327 | paragraph.append(line);
|
---|
328 | }
|
---|
329 | }
|
---|
330 | }
|
---|
331 | }
|
---|
332 | // Write out any outstanding blocks.
|
---|
333 | if(block != null) {
|
---|
334 | if(paragraph != null) {
|
---|
335 | block.insert(paragraph.toString());
|
---|
336 | paragraph = null;
|
---|
337 | }
|
---|
338 | // Check we have somewhere to write to.
|
---|
339 | if(output_file == null) {
|
---|
340 | output_file = new FileOutputStream(text_file.getName() + ".htm");
|
---|
341 | }
|
---|
342 | out(" write: " + block.getName());
|
---|
343 | output_file.write((block.toString()).getBytes());
|
---|
344 | }
|
---|
345 | block = null;
|
---|
346 | paragraph = null;
|
---|
347 | line = null;
|
---|
348 | output_file.close();
|
---|
349 | output_file = null;
|
---|
350 | }
|
---|
351 | catch (Exception error) {
|
---|
352 | error.printStackTrace();
|
---|
353 | System.err.println("An error has occured. View output.txt for more information.");
|
---|
354 | exit();
|
---|
355 | }
|
---|
356 | }
|
---|
357 | }
|
---|
358 | /** Reads in a template file, extracting HTMLBlocks and storing them. It then allows the program to retrieve a block by its name and process it accordingly. */
|
---|
359 | private class TemplateManager
|
---|
360 | extends HashMap {
|
---|
361 | /** Constructor.
|
---|
362 | * @param template_file The <strong>File</strong> template information will be extracted from.
|
---|
363 | */
|
---|
364 | public TemplateManager(File template_file) {
|
---|
365 | out("Building Template Manager:");
|
---|
366 | try {
|
---|
367 | FileReader file_reader = new FileReader(template_file);
|
---|
368 | BufferedReader buffered_reader = new BufferedReader(file_reader);
|
---|
369 | HTMLBlock block = null;
|
---|
370 | String line = null;
|
---|
371 | while((line = buffered_reader.readLine()) != null) {
|
---|
372 | boolean done = false;
|
---|
373 | // Detect a template command.
|
---|
374 | if(line.startsWith("<$")) {
|
---|
375 | // See if this is an open block tag, text insertion tag, or a block closing tag and react appropriately.
|
---|
376 | if(line.startsWith("<$TEXT")) {
|
---|
377 | // Text tag. deal with it below.
|
---|
378 | }
|
---|
379 | else if(line.startsWith("<$/")) {
|
---|
380 | // Block closing tag. If we have an open block close it.
|
---|
381 | if(block != null) {
|
---|
382 | out(" parsed: " + block.getName());
|
---|
383 | // Add to our hashmapping of known blocks.
|
---|
384 | put(block.getName(), block);
|
---|
385 | block = null;
|
---|
386 | done = true;
|
---|
387 | }
|
---|
388 | // Otherwise deal with it below.
|
---|
389 | }
|
---|
390 | // The last option is an open block tag.
|
---|
391 | else {
|
---|
392 | // If have a block open, close it.
|
---|
393 | if(block != null) {
|
---|
394 | out(" parsed: " + block.getName());
|
---|
395 | put(block.getName(), block);
|
---|
396 | block = null;
|
---|
397 | }
|
---|
398 | // Now create a new block with the appropriate name.
|
---|
399 | String name = line.substring(2, line.indexOf(">"));
|
---|
400 | block = new HTMLBlock(name);
|
---|
401 | done = true;
|
---|
402 | }
|
---|
403 | }
|
---|
404 | // Otherwise its just HTML.
|
---|
405 | if(!done) {
|
---|
406 | // If we are building a block append this line.
|
---|
407 | if(block != null) {
|
---|
408 | block.addLine(line);
|
---|
409 | }
|
---|
410 | // Otherwise we just ignore it.
|
---|
411 | else {
|
---|
412 | if(line.length() > 0) {
|
---|
413 | out(" can't parse: " + line);
|
---|
414 | }
|
---|
415 | // Otherwise we're just chewing up blank space.
|
---|
416 | }
|
---|
417 | }
|
---|
418 | }
|
---|
419 | // If we have a block open close it.
|
---|
420 | if(block != null) {
|
---|
421 | out(" parsed: " + block.getName());
|
---|
422 | put(block.getName(), block);
|
---|
423 | }
|
---|
424 | line = null;
|
---|
425 | block = null;
|
---|
426 | buffered_reader.close();
|
---|
427 | buffered_reader = null;
|
---|
428 | file_reader.close();
|
---|
429 | file_reader = null;
|
---|
430 | }
|
---|
431 | catch (Exception error) {
|
---|
432 | error.printStackTrace();
|
---|
433 | System.err.println("An error has occured. View output.txt for more information.");
|
---|
434 | exit();
|
---|
435 | }
|
---|
436 | }
|
---|
437 | /** Retrieve the block indicated by the given name.
|
---|
438 | * @param name The name of the block as a <strong>String</strong>.
|
---|
439 | * @return The <strong>HTMLBlock</strong> asked for or <i>null</i> if no such block.
|
---|
440 | */
|
---|
441 | public HTMLBlock getHTMLBlock(String name) {
|
---|
442 | HTMLBlock block = (HTMLBlock) get(name);
|
---|
443 | // Don't return the original, but a copy.
|
---|
444 | if(block != null) {
|
---|
445 | block = block.spawn();
|
---|
446 | }
|
---|
447 | return block;
|
---|
448 | }
|
---|
449 | }
|
---|
450 | }
|
---|