FileDocCategorySizeDatePackage
AbstractWriter.javaAPI DocJava SE 5 API19412Fri Aug 26 14:58:14 BST 2005javax.swing.text

AbstractWriter

public abstract class AbstractWriter extends Object
AbstractWriter is an abstract class that actually does the work of writing out the element tree including the attributes. In terms of how much is written out per line, the writer defaults to 100. But this value can be set by subclasses.
author
Sunita Mani
version
1.21, 12/19/03

Fields Summary
private ElementIterator
it
private Writer
out
private int
indentLevel
private int
indentSpace
private Document
doc
private int
maxLineLength
private int
currLength
private int
startOffset
private int
endOffset
private int
offsetIndent
private String
lineSeparator
String used for end of line. If the Document has the property EndOfLineStringProperty, it will be used for newlines. Otherwise the System property line.separator will be used. The line separator can also be set.
private boolean
canWrapLines
True indicates that when writing, the line can be split, false indicates that even if the line is > than max line length it should not be split.
private boolean
isLineEmpty
True while the current line is empty. This will remain true after indenting.
private char[]
indentChars
Used when indenting. Will contain the spaces.
private char[]
tempChars
Used when writing out a string.
private char[]
newlineChars
This is used in writeLineSeparator instead of tempChars. If tempChars were used it would mean write couldn't invoke writeLineSeparator as it might have been passed tempChars.
private Segment
segment
Used for writing text.
protected static final char
NEWLINE
How the text packages models newlines.
Constructors Summary
protected AbstractWriter(Writer w, Document doc)
Creates a new AbstractWriter. Initializes the ElementIterator with the default root of the document.

param
w a Writer.
param
doc a Document



                               
         
	this(w, doc, 0, doc.getLength());
    
protected AbstractWriter(Writer w, Document doc, int pos, int len)
Creates a new AbstractWriter. Initializes the ElementIterator with the element passed in.

param
w a Writer
param
doc an Element
param
pos The location in the document to fetch the content.
param
len The amount to write out.

	this.doc = doc;
	it = new ElementIterator(doc.getDefaultRootElement());
	out = w;
	startOffset = pos;
	endOffset = pos + len;
	Object docNewline = doc.getProperty(DefaultEditorKit.
				       EndOfLineStringProperty);
	if (docNewline instanceof String) {
	    setLineSeparator((String)docNewline);
	}
	else {
	    String newline = null;
	    try {
		newline = System.getProperty("line.separator");
	    } catch (SecurityException se) {}
	    if (newline == null) {
		// Should not get here, but if we do it means we could not
		// find a newline string, use \n in this case.
		newline = "\n";
	    }
	    setLineSeparator(newline);
	}
	canWrapLines = true;
    
protected AbstractWriter(Writer w, Element root)
Creates a new AbstractWriter. Initializes the ElementIterator with the element passed in.

param
w a Writer
param
root an Element

	this(w, root, 0, root.getEndOffset());
    
protected AbstractWriter(Writer w, Element root, int pos, int len)
Creates a new AbstractWriter. Initializes the ElementIterator with the element passed in.

param
w a Writer
param
root an Element
param
pos The location in the document to fetch the content.
param
len The amount to write out.

	this.doc = root.getDocument();
	it = new ElementIterator(root);
	out = w;
	startOffset = pos;
	endOffset = pos + len;
	canWrapLines = true;
    
Methods Summary
protected voiddecrIndent()
Decrements the indent level.

	if (offsetIndent > 0) {
	    --offsetIndent;
	}
	else {
	    indentLevel--;
	}
    
protected booleangetCanWrapLines()
Returns whether or not the lines can be wrapped. If this is false no lineSeparator's will be output.

since
1.3

	return canWrapLines;
    
protected intgetCurrentLineLength()
Returns the current line length.

since
1.3.

	return currLength;
    
protected javax.swing.text.DocumentgetDocument()
Fetches the document.

return
the Document.

	return doc;
    
protected javax.swing.text.ElementIteratorgetElementIterator()
Fetches the ElementIterator.

return
the ElementIterator.

	return it;
    
public intgetEndOffset()
Returns the last offset to be output.

since
1.3

	return endOffset;
    
protected intgetIndentLevel()
Returns the current indentation level. That is, the number of times incrIndent has been invoked minus the number of times decrIndent has been invoked.

since
1.3

	return indentLevel;
    
protected intgetIndentSpace()
Returns the amount of space to indent.

since
1.3

	return indentSpace;
    
protected intgetLineLength()
Returns the maximum line length.

since
1.3

	return maxLineLength;
    
public java.lang.StringgetLineSeparator()
Returns the string used to represent newlines.

since
1.3

	return lineSeparator;
    
public intgetStartOffset()
Returns the first offset to be output.

since
1.3

	return startOffset;
    
protected java.lang.StringgetText(javax.swing.text.Element elem)
Returns the text associated with the element. The assumption here is that the element is a leaf element. Throws a BadLocationException when encountered.

param
elem an Element
exception
BadLocationException if pos represents an invalid location within the document
return
the text as a String

	return doc.getText(elem.getStartOffset(),
			   elem.getEndOffset() - elem.getStartOffset());
    
protected java.io.WritergetWriter()
Returns the Writer that is used to output the content.

since
1.3

	return out;
    
protected booleaninRange(javax.swing.text.Element next)
This method determines whether the current element is in the range specified. When no range is specified, the range is initialized to be the entire document. inRange() returns true if the range specified intersects with the element's range.

param
next an Element.
return
boolean that indicates whether the element is in the range.

	int startOffset = getStartOffset();
	int endOffset = getEndOffset();
	if ((next.getStartOffset() >= startOffset && 
	     next.getStartOffset()  < endOffset) ||
	    (startOffset >= next.getStartOffset() &&
	     startOffset < next.getEndOffset())) {
	    return true;
	}
	return false;
    
protected voidincrIndent()
Increments the indent level. If indenting would cause getIndentSpace() *getIndentLevel() to be > than getLineLength() this will not cause an indent.

	// Only increment to a certain point.
	if (offsetIndent > 0) {
	    offsetIndent++;
	}
	else {
	    if (++indentLevel * getIndentSpace() >= getLineLength()) {
		offsetIndent++;
		--indentLevel;
	    }
	}
    
protected voidindent()
Does indentation. The number of spaces written out is indent level times the space to map mapping. If the current line is empty, this will not make it so that the current line is still considered empty.

exception
IOException on any I/O error

	int max = getIndentLevel() * getIndentSpace();
	if (indentChars == null || max > indentChars.length) {
	    indentChars = new char[max];
	    for (int counter = 0; counter < max; counter++) {
		indentChars[counter] = ' ";
	    }
	}
	int length = getCurrentLineLength();
	boolean wasEmpty = isLineEmpty();
	output(indentChars, 0, max);
	if (wasEmpty && length == 0) {
	    isLineEmpty = true;
	}
    
private intindexOf(char[] chars, char sChar, int startIndex, int endIndex)
Support method to locate an occurence of a particular character.

	while(startIndex < endIndex) {
	    if (chars[startIndex] == sChar) {
		return startIndex;
	    }
	    startIndex++;
	}
	return -1;
    
protected booleanisLineEmpty()
Returns true if the current line should be considered empty. This is true when getCurrentLineLength == 0 || indent has been invoked on an empty line.

since
1.3

	return isLineEmpty;
    
protected voidoutput(char[] content, int start, int length)
The last stop in writing out content. All the write methods eventually make it to this method, which invokes write on the Writer.

This method also updates the line length based on length. If this is invoked to output a newline, the current line length will need to be reset as will no longer be valid. If it is up to the caller to do this. Use writeLineSeparator to write out a newline, which will property update the current line length.

since
1.3

	getWriter().write(content, start, length);
	setCurrentLineLength(getCurrentLineLength() + length);
    
protected voidsetCanWrapLines(boolean newValue)
Sets whether or not lines can be wrapped. This can be toggled during the writing of lines. For example, outputting HTML might set this to false when outputting a quoted string.

since
1.3

	canWrapLines = newValue;
    
protected voidsetCurrentLineLength(int length)
Sets the current line length.

since
1.3.

	currLength = length;
	isLineEmpty = (currLength == 0);
    
protected voidsetIndentSpace(int space)
Enables subclasses to specify how many spaces an indent maps to. When indentation takes place, the indent level is multiplied by this mapping. The default is 2.

param
space an int representing the space to indent mapping.

	indentSpace = space;
    
protected voidsetLineLength(int l)
Enables subclasses to set the number of characters they want written per line. The default is 100.

param
l the maximum line length.

	maxLineLength = l;
    
public voidsetLineSeparator(java.lang.String value)
Sets the String used to reprsent newlines. This is initialized in the constructor from either the Document, or the System property line.separator.

since
1.3

	lineSeparator = value;
    
protected voidtext(javax.swing.text.Element elem)
Writes out text. If a range is specified when the constructor is invoked, then only the appropriate range of text is written out.

param
elem an Element.
exception
IOException on any I/O error
exception
BadLocationException if pos represents an invalid location within the document.

	int start = Math.max(getStartOffset(), elem.getStartOffset());
	int end = Math.min(getEndOffset(), elem.getEndOffset());
	if (start < end) {
	    if (segment == null) {
		segment = new Segment();
	    }
	    getDocument().getText(start, end - start, segment);
	    if (segment.count > 0) {
		write(segment.array, segment.offset, segment.count);
	    }
	}
    
protected abstract voidwrite()
This abstract method needs to be implemented by subclasses. Its responsibility is to iterate over the elements and use the write() methods to generate output in the desired format.

protected voidwrite(char ch)
Writes out a character. This is implemented to invoke the write method that takes a char[].

param
ch a char.
exception
IOException on any I/O error

	if (tempChars == null) {
	    tempChars = new char[128];
	}
	tempChars[0] = ch;
	write(tempChars, 0, 1);
    
protected voidwrite(java.lang.String content)
Writes out a string. This is implemented to invoke the write method that takes a char[].

param
content a String.
exception
IOException on any I/O error

	if (content == null) {
	    return;
	}
	int size = content.length();
	if (tempChars == null || tempChars.length < size) {
	    tempChars = new char[size];
	}
	content.getChars(0, size, tempChars, 0);
	write(tempChars, 0, size);
    
protected voidwrite(char[] chars, int startIndex, int length)
All write methods call into this one. If getCanWrapLines() returns false, this will call output with each sequence of chars that doesn't contain a NEWLINE, followed by a call to writeLineSeparator. On the other hand, if getCanWrapLines() returns true, this will split the string, as necessary, so getLineLength is honored. The only exception is if the current string contains no whitespace, and won't fit in which case the line length will exceed getLineLength.

since
1.3

	if (!getCanWrapLines()) {
	    // We can not break string, just track if a newline
	    // is in it.
	    int lastIndex = startIndex;
	    int endIndex = startIndex + length;
	    int newlineIndex = indexOf(chars, NEWLINE, startIndex, endIndex);
	    while (newlineIndex != -1) {
		if (newlineIndex > lastIndex) {
		    output(chars, lastIndex, newlineIndex - lastIndex);
		}
		writeLineSeparator();
		lastIndex = newlineIndex + 1;
		newlineIndex = indexOf(chars, '\n", lastIndex, endIndex);
	    }
	    if (lastIndex < endIndex) {
		output(chars, lastIndex, endIndex - lastIndex);
	    }
	}
	else {
	    // We can break chars if the length exceeds maxLength.
	    int lastIndex = startIndex;
	    int endIndex = startIndex + length;
	    int lineLength = getCurrentLineLength();
	    int maxLength = getLineLength();

	    while (lastIndex < endIndex) {
		int newlineIndex = indexOf(chars, NEWLINE, lastIndex,
					   endIndex);
		boolean needsNewline = false;
                boolean forceNewLine = false;

		lineLength = getCurrentLineLength();
		if (newlineIndex != -1 && (lineLength +
			      (newlineIndex - lastIndex)) < maxLength) {
		    if (newlineIndex > lastIndex) {
			output(chars, lastIndex, newlineIndex - lastIndex);
		    }
		    lastIndex = newlineIndex + 1;
                    forceNewLine = true;
		}
		else if (newlineIndex == -1 && (lineLength +
				(endIndex - lastIndex)) < maxLength) {
		    if (endIndex > lastIndex) {
			output(chars, lastIndex, endIndex - lastIndex);
		    }
		    lastIndex = endIndex;
		}
		else {
		    // Need to break chars, find a place to split chars at,
		    // from lastIndex to endIndex,
		    // or maxLength - lineLength whichever is smaller
		    int breakPoint = -1;
		    int maxBreak = Math.min(endIndex - lastIndex,
					    maxLength - lineLength - 1);
		    int counter = 0;
		    while (counter < maxBreak) {
			if (Character.isWhitespace(chars[counter +
							lastIndex])) {
			    breakPoint = counter;
			}
			counter++;
		    }
		    if (breakPoint != -1) {
			// Found a place to break at.
			breakPoint += lastIndex + 1;
			output(chars, lastIndex, breakPoint - lastIndex);
			lastIndex = breakPoint;
                        needsNewline = true;
		    }
		    else {
			// No where good to break.

                        // find the next whitespace, or write out the
                        // whole string.
			    // maxBreak will be negative if current line too
			    // long.
			    counter = Math.max(0, maxBreak);
			    maxBreak = endIndex - lastIndex;
			    while (counter < maxBreak) {
				if (Character.isWhitespace(chars[counter +
								lastIndex])) {
				    breakPoint = counter;
				    break;
				}
				counter++;
			    }
			    if (breakPoint == -1) {
				output(chars, lastIndex, endIndex - lastIndex);
				breakPoint = endIndex;
			    }
			    else {
				breakPoint += lastIndex;
				if (chars[breakPoint] == NEWLINE) {
				    output(chars, lastIndex, breakPoint++ -
					   lastIndex);
                                forceNewLine = true;
				}
				else {
				    output(chars, lastIndex, ++breakPoint -
					      lastIndex);
                                needsNewline = true;
				}
			    }
			    lastIndex = breakPoint;
			}
		    }
		if (forceNewLine || needsNewline || lastIndex < endIndex) {
		    writeLineSeparator();
                    if (lastIndex < endIndex || !forceNewLine) {
			indent();
		    }
		}
	    }
	}
    
protected voidwriteAttributes(javax.swing.text.AttributeSet attr)
Writes out the set of attributes as " =" pairs. It throws an IOException when encountered.

param
attr an AttributeSet.
exception
IOException on any I/O error


	Enumeration names = attr.getAttributeNames();
	while (names.hasMoreElements()) {
	    Object name = names.nextElement();
	    write(" " + name + "=" + attr.getAttribute(name));
	}
    
protected voidwriteLineSeparator()
Writes the line separator. This invokes output directly as well as setting the lineLength to 0.

since
1.3

	String newline = getLineSeparator();
	int length = newline.length();
	if (newlineChars == null || newlineChars.length < length) {
	    newlineChars = new char[length];
	}
	newline.getChars(0, length, newlineChars, 0);
	output(newlineChars, 0, length);
	setCurrentLineLength(0);