Writer to write output to
* @param doc the javax.swing.text.html.HTMLDocument
* to output
* @param pos position to start outputing the document
* @param len amount to output the document
*/
public HTMLWriter(Writer writer, HTMLDocument doc, int pos, int len)
{
super(writer, doc, pos, len);
outWriter = writer;
htmlDoc = doc;
openEmbeddedTagHashSet = new HashSetjavax.swing.text.html.HTML.Tag,
* javax.swing.text.StyleConstants or
* javax.swing.text.html.HTML.Attribute.ENDTAG.
*
* @param attrSet attrSet to write out
*
* @throws IOException on any I/O exceptions
*/
protected void writeAttributes(AttributeSet attrSet)
throws IOException
{
Enumeration> attrNameEnum = attrSet.getAttributeNames();
while (attrNameEnum.hasMoreElements())
{
Object key = attrNameEnum.nextElement();
Object value = attrSet.getAttribute(key);
// HTML.Attribute.ENDTAG is an instance, not a class.
if (!((key instanceof HTML.Tag) || (key instanceof StyleConstants)
|| (key == HTML.Attribute.ENDTAG)))
{
if (key == HTML.Attribute.SELECTED)
writeRaw(" selected");
else if (key == HTML.Attribute.CHECKED)
writeRaw(" checked");
else
writeRaw(" " + key + "=\"" + value + "\"");
} // if(!((key instanceof HTML.Tag) || (key instanceof
// StyleConstants) || (key == HTML.Attribute.ENDTAG)))
} // while(attrNameEnum.hasMoreElements())
} // protected void writeAttributes(AttributeSet attrSet) throws IOException
/**
* Writes out an empty tag. i.e. a tag without any child elements.
*
* @param paramElem the element to output as an empty tag
*
* @throws IOException on any I/O exceptions
* @throws BadLocationException if a pos is not a valid position in the
* html doc element
*/
protected void emptyTag(Element paramElem)
throws IOException, BadLocationException
{
String elem_name = paramElem.getName();
AttributeSet attrSet = paramElem.getAttributes();
writeRaw("<" + elem_name);
writeAttributes(attrSet);
writeRaw(">");
if (isBlockTag(attrSet))
{
writeRaw("" + elem_name + ">");
} // if(isBlockTag(attrSet))
} // protected void emptyTag(Element paramElem)
// throws IOException, BadLocationException
/**
* Determines if it is a block tag or not.
*
* @param attrSet the attrSet of the element
*
* @return true if it is a block tag
* false if it is a not block tag
*/
protected boolean isBlockTag(AttributeSet attrSet)
{
return ((HTML.Tag)
attrSet.getAttribute(StyleConstants.NameAttribute)).isBlock();
} // protected boolean isBlockTag(AttributeSet attrSet)
/**
* Writes out a start tag. Synthesized elements are skipped.
*
* @param paramElem the element to output as a start tag
* @throws IOException on any I/O exceptions
* @throws BadLocationException if a pos is not a valid position in the
* html doc element
*/
protected void startTag(Element paramElem)
throws IOException, BadLocationException
{
// NOTE: Sysnthesized elements do no call this method at all.
String elem_name = paramElem.getName();
AttributeSet attrSet = paramElem.getAttributes();
indent();
writeRaw("<" + elem_name);
writeAttributes(attrSet);
writeRaw(">");
writeLineSeparator(); // Extra formatting to look more like the RI.
incrIndent();
} // protected void startTag(Element paramElem)
// throws IOException, BadLocationException
/**
* Writes out the contents of a textarea.
*
* @param attrSet the attrSet of the element to output as a text area
* @throws IOException on any I/O exceptions
* @throws BadLocationException if a pos is not a valid position in the
* html doc element
*/
protected void textAreaContent(AttributeSet attrSet)
throws IOException, BadLocationException
{
writeLineSeparator(); // Extra formatting to look more like the RI.
indent();
writeRaw("");
} // protected void textAreaContent(AttributeSet attrSet)
// throws IOException, BadLocationException
/**
* Writes out text, within the appropriate range if it is specified.
*
* @param paramElem the element to output as a text
* @throws IOException on any I/O exceptions
* @throws BadLocationException if a pos is not a valid position in the
* html doc element
*/
protected void text(Element paramElem)
throws IOException, BadLocationException
{
int offset = paramElem.getStartOffset();
int len = paramElem.getEndOffset() - paramElem.getStartOffset();
String txt_value = htmlDoc.getText(offset, len);
writeContent(txt_value);
} // protected void text(Element paramElem)
// throws IOException, BadLocationException
/**
* Writes out the contents of a select element.
*
* @param attrSet the attrSet of the element to output as a select box
*
* @throws IOException on any I/O exceptions
*/
protected void selectContent(AttributeSet attrSet)
throws IOException
{
writeLineSeparator(); // Extra formatting to look more like the RI.
indent();
writeRaw("");
} // protected void selectContent(AttributeSet attrSet) throws IOException
/**
* Writes out the contents of an option element.
*
* @param option the option object to output as a select option
*
* @throws IOException on any I/O exceptions
*/
protected void writeOption(Option option)
throws IOException
{
indent();
writeRaw("");
writeLineSeparator(); // extra formatting to look more like the RI.
} // protected void writeOption(Option option) throws IOException
/**
* Writes out an end tag.
*
* @param paramElem the element to output as an end tag
*
* @throws IOException on any I/O exceptions
*/
protected void endTag(Element paramElem)
throws IOException
{
String elem_name = paramElem.getName();
//writeLineSeparator(); // Extra formatting to look more like the RI.
decrIndent();
indent();
writeRaw("" + elem_name + ">");
writeLineSeparator(); // Extra formatting to look more like the RI.
} // protected void endTag(Element paramElem) throws IOException
/**
* Writes out the comment.
*
* @param paramElem the element to output as a comment
*/
protected void comment(Element paramElem)
throws IOException, BadLocationException
{
AttributeSet attrSet = paramElem.getAttributes();
String comment_str = (String) attrSet.getAttribute(HTML.Attribute.COMMENT);
writeRaw("");
} // protected void comment(Element paramElem)
// throws IOException, BadLocationException
/**
* Determines if element is a synthesized
* javax.swing.text.Element or not.
*
* @param element the element to test
*
* @return true if it is a synthesized element,
* false if it is a not synthesized element
*/
protected boolean synthesizedElement(Element element)
{
AttributeSet attrSet = element.getAttributes();
Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
if (tagType == HTML.Tag.CONTENT || tagType == HTML.Tag.COMMENT
|| tagType == HTML.Tag.IMPLIED)
return true;
else
return false;
} // protected boolean synthesizedElement(Element element)
/**
* Determines if
* javax.swing.text.StyleConstants.NameAttribute
* matches tag or not.
*
* @param attrSet the javax.swing.text.AttributeSet of
* element to be matched
* @param tag the HTML.Tag to match
*
* @return true if it matches,
* false if it does not match
*/
protected boolean matchNameAttribute(AttributeSet attrSet, HTML.Tag tag)
{
Object tagType = attrSet.getAttribute(StyleConstants.NameAttribute);
if (tagType == tag)
return true;
else
return false;
} // protected boolean matchNameAttribute(AttributeSet attrSet,
// HTML.Tag tag)
/**
* Writes out an embedded tag. The tags not already in
* openEmbededTagHashSet will written out.
*
* @param attrSet the javax.swing.text.AttributeSet of
* the element to write out
*
* @throws IOException on any I/O exceptions
*/
protected void writeEmbeddedTags(AttributeSet attrSet)
throws IOException
{
Enumeration> attrNameEnum = attrSet.getAttributeNames();
while (attrNameEnum.hasMoreElements())
{
Object key = attrNameEnum.nextElement();
Object value = attrSet.getAttribute(key);
if (key instanceof HTML.Tag)
{
if (!openEmbeddedTagHashSet.contains(key))
{
writeRaw("<" + key);
writeAttributes((AttributeSet) value);
writeRaw(">");
openEmbeddedTagHashSet.add((HTML.Tag) key);
} // if(!openEmbededTagHashSet.contains(key))
} // if(key instanceof HTML.Tag)
} // while(attrNameEnum.hasMoreElements())
} // protected void writeEmbeddedTags(AttributeSet attrSet)
// throws IOException
/**
* Closes out an unwanted embedded tag. The tags from the
* openEmbededTagHashSet not found in attrSet will be written out.
*
* @param attrSet the AttributeSet of the element to write out
*
* @throws IOException on any I/O exceptions
*/
protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
throws IOException
{
HTML.Tag[] tag_arr =
openEmbeddedTagHashSet.toArray(new HTML.Tag[openEmbeddedTagHashSet.size()]);
for (int i = 0; i < tag_arr.length; i++)
{
HTML.Tag key = tag_arr[i];
if (!attrSet.isDefined(key))
{
writeRaw("" + key.toString() + ">");
openEmbeddedTagHashSet.remove(key);
} // if(!attrSet.isDefined(key))
} // for(int i = 0; i < tag_arr.length; i++)
} // protected void closeOutUnwantedEmbeddedTags(AttributeSet attrSet)
// throws IOException
/**
* Writes out a line separator. Overwrites the parent to write out a new
* line.
*
* @throws IOException on any I/O exceptions.
*/
protected void writeLineSeparator()
throws IOException
{
writeRaw(new_line_str);
} // protected void writeLineSeparator() throws IOException
/**
* Write to the writer. Character entites such as <, >
* are escaped appropriately.
*
* @param chars char array to write out
* @param off offset
* @param len length
*
* @throws IOException on any I/O exceptions
*/
protected void output(char[] chars, int off, int len)
throws IOException
{
CPStringBuilder strBuffer = new CPStringBuilder();
for (int i = 0; i < chars.length; i++)
{
if (isCharHtmlEntity(chars[i]))
strBuffer.append(escapeCharHtmlEntity(chars[i]));
else
strBuffer.append(chars[i]);
} // for(int i = 0; i < chars.length; i++)
writeRaw(strBuffer.toString());
} // protected void output(char[] chars, int off, int len)
// throws IOException
//-------------------------------------------------------------------------
// private methods
/**
* The main method used to traverse through the elements.
*
* @param paramElem element to traverse
*
* @throws IOException on any I/O exceptions
*/
private void traverse(Element paramElem)
throws IOException, BadLocationException
{
Element currElem = paramElem;
AttributeSet attrSet = currElem.getAttributes();
closeOutUnwantedEmbeddedTags(attrSet);
// handle the tag
if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
writeEmbeddedTags(attrSet);
text(currElem);
} // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
if (child_elem_count > 0)
{
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverse(childElem);
} // for(int i = 0; i < child_elem_count; i++)
} // if(child_elem_count > 0)
} // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
} // if(synthesizedElement(paramElem))
else
{
// NOTE: 20061030 - fchoong - title is treated specially here.
// based on RI behavior.
if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
{
boolean fg_is_end_tag = false;
Enumeration> attrNameEnum = attrSet.getAttributeNames();
while (attrNameEnum.hasMoreElements())
{
Object key = attrNameEnum.nextElement();
Object value = attrSet.getAttribute(key);
if (key == HTML.Attribute.ENDTAG && value.equals("true"))
fg_is_end_tag = true;
} // while(attrNameEnum.hasMoreElements())
if (fg_is_end_tag)
writeRaw("");
else
{
indent();
writeRaw("");
int child_elem_count = currElem.getElementCount();
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverse(childElem);
} // for(int i = 0; i < child_elem_count; i++)
writeRaw("");
} // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
{
selectContent(attrSet);
} // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
{
textAreaContent(attrSet);
} // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
else
{
int child_elem_count = currElem.getElementCount();
if (child_elem_count > 0)
{
startTag(currElem);
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverse(childElem);
} // for(int i = 0; i < child_elem_count; i++)
endTag(currElem);
} // if(child_elem_count > 0)
else
{
emptyTag(currElem);
} // else
} // else
} // else
} // private void traverse(Element paramElem)
// throws IOException, BadLocationException
/**
* The method used to traverse through a html fragment.
*
* @param paramElem element to traverse
*
* @throws IOException on any I/O exceptions
*/
private void traverseHtmlFragment(Element paramElem)
throws IOException, BadLocationException
{
// NOTE: This method is similar to traverse(Element paramElem)
Element currElem = paramElem;
boolean fg_is_fragment_parent_elem = false;
boolean fg_is_start_and_end_elem = false;
if (htmlFragmentParentHashSet.contains(paramElem))
fg_is_fragment_parent_elem = true;
if (paramElem == startElem)
fg_pass_start_elem = true;
if (paramElem == startElem && paramElem == endElem)
fg_is_start_and_end_elem = true;
AttributeSet attrSet = currElem.getAttributes();
closeOutUnwantedEmbeddedTags(attrSet);
if (fg_is_fragment_parent_elem || (fg_pass_start_elem
&& fg_pass_end_elem == false) || fg_is_start_and_end_elem)
{
// handle the tag
if (synthesizedElement(paramElem))
{
if (matchNameAttribute(attrSet, HTML.Tag.CONTENT))
{
writeEmbeddedTags(attrSet);
int content_offset = paramElem.getStartOffset();
int content_length = currElem.getEndOffset() - content_offset;
if (doc_offset_remaining > 0)
{
if (content_length > doc_offset_remaining)
{
int split_len = content_length;
split_len = split_len - doc_offset_remaining;
if (split_len > doc_len_remaining)
split_len = doc_len_remaining;
// we need to split it.
String txt_value = htmlDoc.getText(content_offset
+ doc_offset_remaining, split_len);
writeContent(txt_value);
doc_offset_remaining = 0; // the offset is used up.
doc_len_remaining = doc_len_remaining - split_len;
} // if(content_length > doc_offset_remaining)
else
{
// doc_offset_remaining is greater than the entire
// length of content
doc_offset_remaining = doc_offset_remaining
- content_length;
} // else
} // if(doc_offset_remaining > 0)
else if (content_length <= doc_len_remaining)
{
// we can fit the entire content.
text(currElem);
doc_len_remaining = doc_len_remaining - content_length;
} // else if(content_length <= doc_len_remaining)
else
{
// we need to split it.
String txt_value = htmlDoc.getText(content_offset,
doc_len_remaining);
writeContent(txt_value);
doc_len_remaining = 0;
} // else
} // if(matchNameAttribute(attrSet, HTML.Tag.CONTENT))
else if (matchNameAttribute(attrSet, HTML.Tag.COMMENT))
{
comment(currElem);
} // else if(matchNameAttribute(attrSet, HTML.Tag.COMMENT))
else if (matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
{
int child_elem_count = currElem.getElementCount();
if (child_elem_count > 0)
{
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverseHtmlFragment(childElem);
} // for(int i = 0; i < child_elem_count; i++)
} // if(child_elem_count > 0)
} // else if(matchNameAttribute(attrSet, HTML.Tag.IMPLIED))
} // if(synthesizedElement(paramElem))
else
{
// NOTE: 20061030 - fchoong - the isLeaf() condition seems to
// generate the closest behavior to the RI.
if (paramElem.isLeaf())
{
if (doc_offset_remaining > 0)
{
doc_offset_remaining--;
} // if(doc_offset_remaining > 0)
else if (doc_len_remaining > 0)
{
doc_len_remaining--;
} // else if(doc_len_remaining > 0)
} // if(paramElem.isLeaf())
// NOTE: 20061030 - fchoong - title is treated specially here.
// based on RI behavior.
if (matchNameAttribute(attrSet, HTML.Tag.TITLE))
{
boolean fg_is_end_tag = false;
Enumeration> attrNameEnum = attrSet.getAttributeNames();
while (attrNameEnum.hasMoreElements())
{
Object key = attrNameEnum.nextElement();
Object value = attrSet.getAttribute(key);
if (key == HTML.Attribute.ENDTAG && value.equals("true"))
fg_is_end_tag = true;
} // while(attrNameEnum.hasMoreElements())
if (fg_is_end_tag)
writeRaw("");
int child_elem_count = currElem.getElementCount();
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverseHtmlFragment(childElem);
} // for(int i = 0; i < child_elem_count; i++)
writeRaw("");
} // else if(matchNameAttribute(attrSet, HTML.Tag.PRE))
else if (matchNameAttribute(attrSet, HTML.Tag.SELECT))
{
selectContent(attrSet);
} // else if(matchNameAttribute(attrSet, HTML.Tag.SELECT))
else if (matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
{
textAreaContent(attrSet);
} // else if(matchNameAttribute(attrSet, HTML.Tag.TEXTAREA))
else
{
int child_elem_count = currElem.getElementCount();
if (child_elem_count > 0)
{
startTag(currElem);
for (int i = 0; i < child_elem_count; i++)
{
Element childElem = paramElem.getElement(i);
traverseHtmlFragment(childElem);
} // for(int i = 0; i < child_elem_count; i++)
endTag(currElem);
} // if(child_elem_count > 0)
else
{
emptyTag(currElem);
} // else
} // else
} // else
} // if(fg_is_fragment_parent_elem || (fg_pass_start_elem
// && fg_pass_end_elem == false) || fg_is_start_and_end_elem)
if (paramElem == endElem)
fg_pass_end_elem = true;
} // private void traverseHtmlFragment(Element paramElem)
// throws IOException, BadLocationException
/**
* Write to the writer without any modifications.
*
* @param param_str the str to write out
*
* @throws IOException on any I/O exceptions
*/
private void writeRaw(String param_str)
throws IOException
{
super.output(param_str.toCharArray(), 0, param_str.length());
} // private void writeRaw(char[] chars, int off, int len)
// throws IOException
/**
* Write to the writer, escaping HTML character entitie where neccessary.
*
* @param param_str the str to write out
*
* @throws IOException on any I/O exceptions
*/
private void writeContent(String param_str)
throws IOException
{
char[] str_char_arr = param_str.toCharArray();
if (hasHtmlEntity(param_str))
output(str_char_arr, 0, str_char_arr.length);
else
super.output(str_char_arr, 0, str_char_arr.length);
} // private void writeContent(String param_str) throws IOException
/**
* Use this for debugging. Writes out all attributes regardless of type.
*
* @param attrSet the javax.swing.text.AttributeSet to
* write out
*
* @throws IOException on any I/O exceptions
*/
private void writeAllAttributes(AttributeSet attrSet)
throws IOException
{
Enumeration> attrNameEnum = attrSet.getAttributeNames();
while (attrNameEnum.hasMoreElements())
{
Object key = attrNameEnum.nextElement();
Object value = attrSet.getAttribute(key);
writeRaw(" " + key + "=\"" + value + "\"");
writeRaw(" " + key.getClass().toString() + "=\""
+ value.getClass().toString() + "\"");
} // while(attrNameEnum.hasMoreElements())
} // private void writeAllAttributes(AttributeSet attrSet)
// throws IOException
/**
* Tests if the str contains any html entities.
*
* @param param_str the str to test
*
* @return true if it has a html entity
* false if it does not have a html entity
*/
private boolean hasHtmlEntity(String param_str)
{
boolean ret_bool = false;
for (int i = 0; i < html_entity_char_arr.length; i++)
{
if (param_str.indexOf(html_entity_char_arr[i]) != -1)
{
ret_bool = true;
break;
} // if(param_str.indexOf(html_entity_char_arr[i]) != -1)
} // for(int i = 0; i < html_entity_char_arr.length; i++)
return ret_bool;
} // private boolean hasHtmlEntity(String param_str)
/**
* Tests if the char is a html entities.
*
* @param param_char the char to test
*
* @return true if it is a html entity
* false if it is not a html entity.
*/
private boolean isCharHtmlEntity(char param_char)
{
boolean ret_bool = false;
for (int i = 0; i < html_entity_char_arr.length; i++)
{
if (param_char == html_entity_char_arr[i])
{
ret_bool = true;
break;
} // if(param_char == html_entity_char_arr[i])
} // for(int i = 0; i < html_entity_char_arr.length; i++)
return ret_bool;
} // private boolean hasHtmlEntity(String param_str)
/**
* Escape html entities.
*
* @param param_char the char to escape
*
* @return escaped html entity. Original char is returned as a str if is
* is not a html entity
*/
private String escapeCharHtmlEntity(char param_char)
{
String ret_str = "" + param_char;
for (int i = 0; i < html_entity_char_arr.length; i++)
{
if (param_char == html_entity_char_arr[i])
{
ret_str = html_entity_escape_str_arr[i];
break;
} // if(param_char == html_entity_char_arr[i])
} // for(int i = 0; i < html_entity_char_arr.length; i++)
return ret_str;
} // private String escapeCharHtmlEntity(char param_char)
} // public class HTMLWriter extends AbstractWriter