001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: package de.uka.ilkd.key.util.keydoc.html;
009:
010: import java.io.BufferedWriter;
011: import java.io.File;
012: import java.io.FileWriter;
013: import java.io.FileNotFoundException;
014: import java.io.FilenameFilter;
015: import java.io.IOException;
016: import java.util.LinkedList;
017:
018: import de.uka.ilkd.key.util.KeYResourceManager;
019:
020: /** This class represents the director of the builder design pattern.
021: It creates the datastucture, directs the KeYToHTMLBuilder and stores the {@link keydoc.BoxedFile BoxedFiles} it gets from the builder.
022: */
023: class Director {
024:
025: String[] args;
026: boolean rek = false;
027: File currentFolder = new File(System.getProperty("user.dir"));
028: //File startFolder= new File(System.getProperty("user.dir");
029:
030: private File[] toProcess; // Files to process
031: private LinkedList allFolders = new LinkedList(); // The processed folders
032: private LinkedList processed = new LinkedList(); // Already processed Files (In other folders).
033:
034: private final String docFolder = "KeYDoc";
035:
036: /** Creates a new Director.*/
037: public Director(String[] args, File currentFolder, boolean rek) {
038: //try {
039: this .args = args;
040: this .rek = rek;
041: this .currentFolder = currentFolder;
042: /* }
043: catch (IOException ioe) {
044: System.out.println(ioe + " occured, because your input pathname couldn't be resolved.");
045: }*/
046: }
047:
048: /** Creates a new Director.*/
049: public Director(String[] args, boolean rek) {
050: this .args = args;
051: this .rek = rek;
052: }
053:
054: /* Should evaluate which key files should be documented and
055: * returned.
056: */
057: private File[] getKeYs(String[] which) {
058: KDFilenameFilter filter = new KDFilenameFilter(which);
059: try {
060: System.out.println("Looking for KeY Files in Folder "
061: + currentFolder.getPath());
062: return currentFolder.listFiles(filter);
063: } catch (Exception e) {
064: System.out
065: .println("Exception while looking for matching files: "
066: + e);
067: return null;
068: }
069:
070: }
071:
072: /** The main construction method.
073: This method constructs the whole HTML data structure
074: @return returns true if the files in this folders have been successfully built. (also false if there were no files to build)
075: */
076: private boolean construct() {
077: try {
078:
079: if (rek) {
080: Director d;
081: String[] foldersInDir = currentFolder
082: .list(new FolderFilenameFilter(docFolder));
083:
084: for (int i = 0; i < foldersInDir.length; i++) {
085: if (!currentFolder
086: /*.getCanonicalFile()*/.getName().equals(
087: System.getProperty("user.dir")))
088: d = new Director(args, new File(currentFolder,
089: foldersInDir[i]), rek);
090: else
091: d = new Director(args,
092: new File(foldersInDir[i]), rek);
093:
094: LinkedList[] returnValue = d.constructAndReturn();
095:
096: for (int j = 0; j < returnValue[0].size(); j++) {
097: ShortBox toSort = (ShortBox) returnValue[0]
098: .get(j);
099: sortInProcessed(toSort);
100: }
101:
102: for (int j = 0; j < returnValue[1].size(); j++) {
103: File toSort = (File) returnValue[1].get(j);
104: sortFileInLL(toSort, allFolders);
105: }
106:
107: }
108:
109: }
110:
111: // Get the Files to process in this folder
112: toProcess = getKeYs(args);
113:
114: if (toProcess == null)
115: throw new NullPointerException();
116:
117: if (toProcess.length == 0)
118: throw new Exception("No matches in folder: "
119: + currentFolder.getName());
120:
121: BoxedFile htmlFile = null;
122:
123: StringBuffer this start = new StringBuffer();
124: makeStartHeader(this start);
125: StringBuffer this links = new StringBuffer();
126: makeLinksHeader(this links, pathToName(currentFolder
127: .getPath()));
128:
129: // Create thisindex.html
130: String indexstr = ("<html><head><title>KeYDoc Documentation</title></head><frameset cols=\"200,*\"> <!-- Frameset-Definition --><frameset rows=\"300,*\"><frame src=\"folders.html\" name=\"navigation\"><frame src=\""
131: + pathToName(currentFolder.getPath())
132: + "links.html\" name=\"navigation\"> </frameset> <!-- Frame-Window-Definition --> <frame src=\""
133: + pathToName(currentFolder.getPath()) + "start.html\" name=\"start\"> <!-- Frame-Window-Definition --><noframes><body><h1>No Frames</h1><p>Your Browser can't show frames.</p><p>KeYDoc is at the moment not fit to show KeY documentation on your Browser. Turn on frames to watch the KeYdoc.</p></body></noframes></frameset></html>");
134: writeFile(docFolder + File.separator
135: + pathToName(currentFolder.getPath())
136: + "index.html", indexstr);
137:
138: // Building the documentation Files and sorting them into the processed LinkedList.
139: loop: for (int i = 0; i < toProcess.length; i++) {
140:
141: System.out.println("Building file: "
142: + toProcess[i].getName());
143: htmlFile = KDKeYToHTMLBuilder
144: .buildHTMLFile(toProcess[i]);
145:
146: if (htmlFile == null) // an Error occured during parsing. Skip this file
147: continue loop;
148:
149: String newFile = htmlFile.getFile().getName();
150:
151: // This monster extracts the first line of text out of the HTMLFile.
152: String shortDescription = htmlFile.getHtmlFile()
153: .getHTMLFileAsString().substring(
154: htmlFile.getFirstOffset(),
155: htmlFile.getFirstOffset()
156: + htmlFile.getFirstLength());
157:
158: // Write Documentation File
159: // fileToWrite points to the file. It is relative to the path, there KeYDoc was started.
160: String fileToWrite = docFolder + File.separator
161: + currentFolder.getPath() + File.separator
162: + newFile; // the file, which should be written. Attention: without the .html ending! Search the file for .html for more explanation.
163: writeFile(fileToWrite + ".html", htmlFile.getHtmlFile()
164: .getHTMLFileAsString());
165:
166: String path = currentFolder.getPath() + File.separator
167: + newFile;
168: path = path.substring(1, path.length());
169:
170: // Create thisstart.html
171: this start
172: .append("<tr><code><td class=\"left\" valign=\"top\"><code><a href=\"");
173: this start.append(path + ".html");
174: this start.append("\">");
175: this start.append(newFile);
176: this start.append("</a></td><td class=\"right\">");
177: this start.append(shortDescription);
178: this start.append("</td></code></tr>");
179:
180: // Create thislinks.html
181: this links.append("<a href=\"");
182: this links.append(path + ".html");
183: this links.append("\" target=\"start\">");
184: this links.append(newFile);
185: this links.append("</a><br>");
186:
187: ShortBox toSort = new ShortBox(new File(currentFolder
188: .getPath()
189: + File.separator + newFile), shortDescription);
190: sortInProcessed(toSort);
191:
192: }
193:
194: // Write thislinks and thisstart
195: this links.append("</body></html>");
196: writeFile(docFolder + File.separator
197: + pathToName(currentFolder.getPath())
198: + "links.html", this links.toString());
199: this start.append("</table></center><br>");
200: writeFile(docFolder + File.separator
201: + pathToName(currentFolder.getPath())
202: + "start.html", this start.toString());
203:
204: return true;
205: } catch (NullPointerException nPE) {
206: return false;
207: } catch (Exception e) {
208: System.out.println(e.getMessage());
209: return false;
210: }
211: }
212:
213: // returns a LinkedList of constructed ShortBoxes.
214: private LinkedList[] constructAndReturn() {
215: boolean built = this .construct();
216: if (built)
217: sortFileInLL(currentFolder, allFolders);
218:
219: LinkedList[] ret = new LinkedList[2];
220: ret[0] = processed;
221:
222: ret[1] = allFolders;
223:
224: return ret;
225: }
226:
227: // this is the method called by keydoc. Starts construction and finishes it by building the "All Folders" files.
228: public void startConstruct() {
229:
230: buildDataStructure();
231:
232: boolean built = this .construct();
233: if (built)
234: sortFileInLL(currentFolder, allFolders);
235:
236: StringBuffer start = new StringBuffer();
237: makeStartHeader(start);
238: StringBuffer links = new StringBuffer();
239: makeLinksHeader(links, "");
240: StringBuffer folders = new StringBuffer();
241: makeFoldersHeader(folders);
242:
243: // Create folders.html
244: for (int i = 0; i < allFolders.size(); i++) {
245: File folder = (File) allFolders.get(i);
246: folders.append("<a href=\"" + pathToName(folder.getPath())
247: + "index.html\" target=\"_parent\">"
248: + folder.getName() + "</a><br>");
249: }
250: folders.append("</body></html>");
251: writeFile(docFolder + File.separator + "folders.html", folders
252: .toString());
253:
254: // Writing links in start.html, links.html
255: ShortBox currentFile = null;
256: for (int i = 0; i < processed.size(); i++) {
257:
258: currentFile = (ShortBox) processed.get(i);
259: String path = currentFile.getFile().getPath();
260: String name = currentFile.getFile().getName();
261:
262: // Create start.html
263: start
264: .append("<tr><code><td class=\"left\" valign=\"top\"><code><a href=\"");
265: start.append(path.substring(1, path.length()) + ".html");
266: start.append("\">");
267: start.append(name); // This is why the .html ending isn't attached right to the file.
268: start.append("</a></td><td class=\"right\">");
269: start.append(currentFile.getDescription());
270: start.append("</td></code></tr>");
271:
272: // Create links.html
273: links.append("<a href=\"");
274: links.append(path.substring(1, path.length()) + ".html");
275: links.append("\" target=\"start\">");
276: links.append(name);
277: links.append("</a><br>");
278:
279: }
280:
281: links.append("</body></html>");
282: writeFile(docFolder + File.separator + "links.html", links
283: .toString());
284:
285: start.append("</table></center><br>");
286: writeFile(docFolder + File.separator + "start.html", start
287: .toString());
288:
289: }
290:
291: private void copyLogo(String target) {
292: KeYResourceManager.getManager().copyIfNotExists(Director.class,
293: "logo/KeYLogo.png", target);
294: }
295:
296: /* Create a file */
297: private void writeFile(String name, String text) {
298:
299: File toWrite;
300: FileWriter fw;
301: BufferedWriter bw;
302:
303: try {
304: toWrite = new File(name);
305: System.out.print("Writing file: " + toWrite.toString()
306: + "...");
307: File neededFolders = toWrite.getParentFile();
308: neededFolders.mkdirs();
309: toWrite.createNewFile();
310: fw = new FileWriter(toWrite);
311: bw = new BufferedWriter(fw);
312: bw.write(text);
313: bw.close();
314: System.out.println(" done");
315: } catch (FileNotFoundException fNFE) {
316: System.out
317: .println("FileNotFoundException: File not found or accessable.");
318: } catch (IOException iOE) {
319: System.out
320: .println("IOException occured during writing KeYdoc files.");
321: } catch (Exception e) {
322: System.out.println("Exception: " + e);
323: }
324: }
325:
326: // Sorts the ShortBox toSort into the sorted processed Array, using binary search
327: private void sortInProcessed(ShortBox toSort) {
328:
329: String newFile = toSort.getFile().getName();
330: // Sort the file into the processed array
331: boolean sorted = false;
332: int last = processed.size() - 1;
333: int first = 0;
334: int middle;
335:
336: String selFile;
337:
338: if (processed.size() == 0)
339: processed.add(toSort);
340: else
341: while (!sorted) {
342:
343: middle = first + (last - first) / 2;
344: selFile = ((ShortBox) processed.get(middle)).getFile()
345: .getName();
346:
347: if (newFile.compareToIgnoreCase(selFile) > 0) {
348: if (processed.size() > middle + 1) // index starts at 0.
349: if (newFile
350: .compareToIgnoreCase(((ShortBox) processed
351: .get(middle + 1)).getFile()
352: .getName()) > 0)
353: first = middle + 1;
354: else {
355: processed.add(middle + 1, toSort);
356: sorted = true;
357: }
358: else {
359: processed.add(middle + 1, toSort);
360: sorted = true;
361: }
362: } else if (newFile.compareToIgnoreCase(selFile) < 0) {
363: if (middle > 0) // index starts at 0.
364: if (newFile
365: .compareToIgnoreCase(((ShortBox) processed
366: .get(middle - 1)).getFile()
367: .getName()) < 0)
368: last = middle - 1;
369: else {
370: processed.add(middle, toSort);
371: sorted = true;
372: }
373: else {
374: processed.add(middle, toSort);
375: sorted = true;
376: }
377: } else {
378: processed.add(middle, toSort);
379: sorted = true;
380: }
381: }
382: }
383:
384: // Sorts a File in a Linkedlist of File, using binary search
385: private void sortFileInLL(File toSort, LinkedList list) {
386:
387: // Sort the file into the list array
388: boolean sorted = false;
389: int last = list.size() - 1;
390: int first = 0;
391: int middle;
392:
393: File selFile;
394:
395: if (list.size() == 0)
396: list.add(toSort);
397: else
398: while (!sorted) {
399:
400: middle = first + (last - first) / 2;
401: selFile = (File) list.get(middle);
402:
403: if (toSort.getName().compareToIgnoreCase(
404: selFile.getName()) > 0) {
405: if (list.size() > middle + 1) // index starts at 0.
406: if (toSort.getName()
407: .compareToIgnoreCase(
408: ((File) list.get(middle + 1))
409: .getName()) > 0)
410: first = middle + 1;
411: else {
412: list.add(middle + 1, toSort);
413: sorted = true;
414: }
415: else {
416: list.add(middle + 1, toSort);
417: sorted = true;
418: }
419: } else if (toSort.getName().compareToIgnoreCase(
420: selFile.getName()) < 0) {
421: if (middle > 0) // index starts at 0.
422: if (toSort.getName()
423: .compareToIgnoreCase(
424: ((File) list.get(middle - 1))
425: .getName()) < 0)
426: last = middle - 1;
427: else {
428: list.add(middle, toSort);
429: sorted = true;
430: }
431: else {
432: list.add(middle, toSort);
433: sorted = true;
434: }
435: } else {
436: list.add(middle, toSort);
437: sorted = true;
438: }
439: }
440: }
441:
442: // Turns a pathname into a name for a file.
443: private String pathToName(String path) {
444: String ret = "";
445: for (int i = 0; i < path.length(); i++)
446: if (path.charAt(i) != File.separatorChar)
447: ret += path.charAt(i);
448:
449: return ret;
450: }
451:
452: /* Builds all the necessary folders and other files.
453: */
454: private void buildDataStructure() {
455:
456: File dir = new File(currentFolder, docFolder);
457: System.out.print("Building folder: " + dir.toString() + "...");
458: boolean success = dir.mkdir();
459: if (!success)
460: System.out
461: .println("Warning: Directory couldn't be created. Does folder "
462: + docFolder + " already exist?");
463: else
464: System.out.println("done");
465:
466: // Create index.html
467: String indexstr = ("<html><head><title>KeYDoc Documentation</title></head><frameset cols=\"200,*\"> <!-- Frameset-Definition --><frameset rows=\"300,*\"><frame src=\"folders.html\" name=\"navigation\"><frame src=\"links.html\" name=\"navigation\"> </frameset> <!-- Frame-Window-Definition --> <frame src=\"start.html\" name=\"start\"> <!-- Frame-Window-Definition --><noframes><body><h1>No Frames</h1><p>Your Browser can't show frames.</p><p>KeYDoc is at the moment not fit to show KeY documentation on your Browser. Turn on frames to watch the KeYdoc.</p></body></noframes></frameset></html>");
468: writeFile(docFolder + File.separator + "index.html", indexstr);
469:
470: }
471:
472: private void makeStartHeader(StringBuffer start) {
473: start
474: .append("<html><head><title>KeYDoc start</title></head><body>");
475: start
476: .append("<center><table border=\"1\" width=\"80%\"><tr><td colspan=\"1\" bgcolor=\"#BEBEFF\"><h2>Current Folder: ");
477: start.append(currentFolder.getPath());
478: start.append("</h2></td></tr></table><br><br>");
479: start
480: .append("<table border=\"1\" width=\"80%\"><colgroup><col width=\"1*\"><col width=\"5*\"></colgroup><tr><td colspan=\"1\" bgcolor=\"#BEBEFF\"><h2>.key Summary</h2></td><td colspan=\"1\" bgcolor=\"#BEBEFF\"> </td></tr>");
481: }
482:
483: private void makeLinksHeader(StringBuffer links, String folder) {
484: links
485: .append("<html><head><title>KeYDoc links</title></head><body>");
486: links.append("<br><a href=\"" + folder
487: + "start.html\" target=\"start\">start</a><br><br>");
488: }
489:
490: private void makeFoldersHeader(StringBuffer folders) {
491: folders
492: .append("<html><head><title>KeYDoc folders</title></head><body>");
493: folders
494: .append("<center><font size=\"7\"><font color=\"#008040\">K</font><font color=\"#0000FF\">e</font><font color=\"#008040\">Y</font></font><font size=\"0\">Doc</font></center><br><br>");
495: folders
496: .append("<a href=\"index.html\" target=\"_parent\">All folders</a><br><br>");
497: }
498:
499: }
500:
501: // accepts all folders except the docfolder
502: class FolderFilenameFilter implements FilenameFilter {
503: private String docFolder;
504:
505: public FolderFilenameFilter(String docFolder) {
506: this .docFolder = docFolder;
507: }
508:
509: public boolean accept(File dir, String name) {
510: boolean ret = (new File(dir, name).isDirectory())
511: && !name.equals(docFolder);
512: //System.out.println(name + " " + ret);
513: return ret;
514: }
515: }
516:
517: // ShortBox boxes the Filename + Shortdescription.
518: class ShortBox {
519: private File File;
520: private String description;
521:
522: public ShortBox(File File, String description) {
523: this .File = File;
524: this .description = description;
525: }
526:
527: public File getFile() {
528: return File;
529: }
530:
531: public String getDescription() {
532: return description;
533: }
534: }
|