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