package org.eclipse.ui.examples.readmetool; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import java.io.*; | |
import java.util.Hashtable; | |
import java.util.Vector; | |
import org.eclipse.core.resources.IFile; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IAdaptable; | |
/** | |
* This class is a simple parser implementing the IReadmeFileParser | |
* interface. It parses a Readme file into sections based on the | |
* existence of numbered section tags in the input. A line beginning | |
* with a number followed by a dot will be taken as a section indicator | |
* (for example, 1., 2., or 12.). | |
* As well, a line beginning with a subsection-style series of numbers | |
* will also be taken as a section indicator, and can be used to | |
* indicate subsections (for example, 1.1, or 1.1.12). | |
*/ | |
public class DefaultSectionsParser implements IReadmeFileParser { | |
/** | |
* Returns the mark element that is the logical parent | |
* of the given mark number. Each dot in a mark number | |
* represents a parent-child separation. For example, | |
* the parent of 1.2 is 1, the parent of 1.4.1 is 1.4. | |
* Returns null if there is no appropriate parent. | |
*/ | |
protected IAdaptable getParent(Hashtable toc, String number) { | |
int lastDot = number.lastIndexOf('.'); | |
if (lastDot < 0) | |
return null; | |
String parentNumber = number.substring(0, lastDot); | |
return (IAdaptable) toc.get(parentNumber); | |
} | |
/** | |
* Returns a string containing the contents of the given | |
* file. Returns an empty string if there were any errors | |
* reading the file. | |
*/ | |
protected String getText(IFile file) { | |
try { | |
InputStream in = file.getContents(); | |
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
byte[] buf = new byte[1024]; | |
int read = in.read(buf); | |
while (read > 0) { | |
out.write(buf, 0, read); | |
read = in.read(buf); | |
} | |
return out.toString(); | |
} catch (CoreException e) { | |
} catch (IOException e) { | |
} | |
return ""; //$NON-NLS-1$ | |
} | |
/** | |
* Parses the input given by the argument. | |
* | |
* @param file the element containing the input text | |
* @return an element collection representing the parsed input | |
*/ | |
public MarkElement[] parse(IFile file) { | |
Hashtable markTable = new Hashtable(40); | |
Vector topLevel = new Vector(); | |
String s = getText(file); | |
int start = 0; | |
int end = -1; | |
int lineno = 0; | |
int lastlineno = 0; | |
MarkElement lastme = null; | |
int ix; | |
// parse content for headings | |
ix = s.indexOf('\n', start); | |
while (ix != -1) { | |
start = end + 1; | |
end = ix = s.indexOf('\n', start); | |
lineno++; | |
if (ix != -1) { | |
// skip blanks | |
while (s.charAt(start) == ' ' || s.charAt(start) == '\t') { | |
start++; | |
} | |
if (Character.isDigit(s.charAt(start))) { | |
if (lastme != null) { | |
lastme.setNumberOfLines(lineno - lastlineno - 1); | |
} | |
lastlineno = lineno; | |
String markName = parseHeading(s, start, end); | |
//get the parent mark, if any. | |
String markNumber = parseNumber(markName); | |
IAdaptable parent = getParent(markTable, markNumber); | |
if (parent == null) | |
parent = file; | |
MarkElement me = new MarkElement(parent, markName, start, end - start); | |
lastme = me; | |
markTable.put(markNumber, me); | |
if (parent == file) { | |
topLevel.add(me); | |
} | |
} | |
} | |
} | |
if (lastme != null) { | |
// set the number of lines for the last section | |
lastme.setNumberOfLines(lineno - lastlineno - 1); | |
} | |
MarkElement[] results = new MarkElement[topLevel.size()]; | |
topLevel.copyInto(results); | |
return results; | |
} | |
/** | |
* Creates a section name from the buffer and trims trailing | |
* space characters. | |
* | |
* @param buffer the string from which to create the section name | |
* @param start the start index | |
* @param end the end index | |
* @return a section name | |
*/ | |
private String parseHeading(String buffer, int start, int end) { | |
while (Character.isWhitespace(buffer.charAt(end-1)) && end >start) { | |
end--; | |
} | |
return buffer.substring(start, end); | |
} | |
/** | |
* Returns the number for this heading. A heading consists | |
* of a number (an arbitrary string of numbers and dots), followed by | |
* arbitrary text. | |
*/ | |
protected String parseNumber(String heading) { | |
int start = 0; | |
int end = heading.length(); | |
char c; | |
do { | |
c = heading.charAt(start++); | |
} while ((c == '.' || Character.isDigit(c)) && start < end); | |
//disregard trailing dots | |
while (heading.charAt(start-1) == '.' && start > 0) { | |
start--; | |
} | |
return heading.substring(0, start); | |
} | |
} |