001: /*
002: * Created on Feb 10, 2005
003: */
004: package com.sun.portal.wireless.htmlconversion.processors;
005:
006: import java.util.HashMap;
007:
008: import org.w3c.dom.Element;
009:
010: import com.sun.portal.wireless.htmlconversion.GenericHtmlParserCallback;
011: import com.sun.portal.wireless.htmlconversion.ParserState;
012:
013: /**
014: * Tag processor to handle all text elements.
015: *
016: * @author ashwin.mathew@sun.com
017: */
018: public class AmlTextTagProcessor extends BaseTagProcessor {
019:
020: // Output tag name
021: public static final String AML_TEXT = "AmlText";
022:
023: // Attributes on AmlText
024: public static final String ATTR_TEXT = "text";
025: public static final String ATTR_TEXTSIZE = "textsize";
026: public static final String ATTR_HALIGN = "halign";
027: public static final String ATTR_VALIGN = "valign";
028: public static final String ATTR_FONT = "font";
029: public static final String ATTR_ITALICS = "italics";
030: public static final String ATTR_BOLD = "bold";
031: public static final String ATTR_UNDERLINE = "underline";
032: public static final String ATTR_COLOR = "color";
033:
034: // Attributes from font tag
035: public static final String ATTR_FONT_FACE = "face";
036: public static final String ATTR_FONT_COLOR = "color";
037: public static final String ATTR_FONT_SIZE = "size";
038:
039: // Values for font size
040: public static final int VAL_FONT_SIZE_SMALL = 2;
041: public static final int VAL_FONT_SIZE_NORMAL = 4;
042: public static final int VAL_FONT_SIZE_BIG = 6;
043:
044: // Values for attributes
045: public static final String VAL_TRUE = "true";
046: public static final String VAL_FALSE = "false";
047:
048: private static final char CHAR_PLUS = '+';
049: private static final char CHAR_MINUS = '-';
050:
051: /* (non-Javadoc)
052: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#getAmlTag()
053: */
054: public String getAmlTag() {
055: return AML_TEXT;
056: }
057:
058: /* (non-Javadoc)
059: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#getSupportedTags()
060: */
061: public String[] getSupportedTags() {
062: return TextTag.getStyleTagNames();
063: }
064:
065: /* (non-Javadoc)
066: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#processTag(java.lang.String, java.util.HashMap, com.sun.portal.wireless.htmlconversion.HtmlParserCallback)
067: */
068: public Element startTag(String tagName, HashMap attributes,
069: ParserState state) {
070: // Set the text style on ParserState
071: TextTag newStyle = null;
072:
073: TextTag currentStyle = state.getTextTagContext();
074:
075: // add specialized handling for font tag
076: if (tagName.equals(TextTag.FONT.getTagName())) {
077: String font = (String) attributes.get(ATTR_FONT_FACE);
078: String color = (String) attributes.get(ATTR_FONT_COLOR);
079: String sizeStr = (String) attributes.get(ATTR_FONT_SIZE);
080:
081: int sizeInt = VAL_FONT_SIZE_NORMAL;
082: if (sizeStr != null) {
083: int sign = 1;
084:
085: if (sizeStr.length() >= 2) {
086: // It's a relative font size. We have to get the
087: // current font size and add this value to it
088: // to get the new font size.
089:
090: // Get the sign
091: char signChar = sizeStr.charAt(0);
092: if (signChar == CHAR_PLUS) {
093: sign = 1;
094: } else if (signChar == CHAR_MINUS) {
095: sign = -1;
096: }
097:
098: // Get the number
099: sizeStr = sizeStr.substring(1);
100:
101: TextTag currentTextTag = state.getTextTagContext();
102: String currentTextSize = currentTextTag
103: .getTextSize();
104:
105: // Choose a default median value
106: int currentFontSize = VAL_FONT_SIZE_NORMAL;
107:
108: if (currentTextSize.equals(TextTag.TEXT_SIZE_SMALL)) {
109: currentFontSize = VAL_FONT_SIZE_SMALL;
110: } else if (currentTextSize
111: .equals(TextTag.TEXT_SIZE_BIG)) {
112: currentFontSize = VAL_FONT_SIZE_BIG;
113: }
114:
115: sizeInt = (Integer.parseInt(sizeStr) * sign)
116: + currentFontSize;
117: } else {
118: sizeInt = Integer.parseInt(sizeStr);
119: }
120: }
121:
122: String size = null;
123:
124: if (sizeInt <= 2) // Small size
125: {
126: size = TextTag.TEXT_SIZE_SMALL;
127: } else if (sizeInt >= 6) // Large size
128: {
129: size = TextTag.TEXT_SIZE_BIG;
130: }
131:
132: newStyle = new TextTag(font, color, size);
133: } else {
134: newStyle = TextTag.getStyle(tagName);
135: }
136:
137: state.setTextTagContext(newStyle);
138:
139: // If a leading line break is required,
140: // add an AmlBr to the current output container
141: if (newStyle.hasLeadingLineBreak()) {
142: Element amlBr = AmlBrTagProcessor.createAmlBrElement(state);
143: GenericHtmlParserCallback.appendChildToOutputContainer(
144: state, amlBr);
145: }
146:
147: // If it's a dt tag, it means we have to create
148: // a definition list - make the AmlListItem here
149: // There's no need to append the AmlText element,
150: // that will be done in HtmlParserCallback once
151: // the AmlListItem is set as the current output tag
152: if (tagName.equals(TextTag.DT.getTagName())) {
153: Element amlListItem = AmlListItemTagProcessor
154: .createAmlListItemElement(state);
155: GenericHtmlParserCallback.appendChildToOutputContainer(
156: state, amlListItem);
157: state.setOutputContainerTag(amlListItem);
158: state.setCurrentOutputTag(amlListItem);
159: }
160:
161: // We'll set the text at endTag or interruptedTag
162: Element element = createAmlTextElement(null, state);
163:
164: return element;
165: }
166:
167: /* (non-Javadoc)
168: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#encounteredChild(org.w3c.dom.Element)
169: */
170: public Element interruptedTag(ParserState state) {
171: Element element = state.getCurrentOutputTag();
172: String elementText = element.getAttribute(ATTR_TEXT);
173:
174: if (state.isTextAvailable()) {
175: /* Removed this block of code, since it sometimes incorrectly
176: * overwrites text data
177: if (element.getTagName().equals(AML_TEXT))
178: {
179: element.setAttribute(ATTR_TEXT, state.getText());
180: }
181: else
182: {
183: element = createAmlTextElement(state.getText(), state);
184: }*/
185:
186: element = createAmlTextElement(state.getText(), state);
187:
188: state.clearText();
189: } else if (element.getTagName().equals(AML_TEXT)
190: && (elementText == null || (elementText != null && elementText
191: .length() == 0))) {
192: // If no text is available, and child is encountered,
193: // the AmlText element with null text in it created on
194: // startTag() must be removed from the output DOM tree
195: Element parent = state.getOutputContainerTag();
196: parent.removeChild(element);
197: state.rollbackCurrentOutputTag();
198: }
199:
200: return element;
201: }
202:
203: /* (non-Javadoc)
204: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#endTag(org.w3c.dom.Element)
205: */
206: public Element endTag(String tag, ParserState state) {
207: Element element = null;
208: Element currentTag = state.getCurrentOutputTag();
209:
210: if (state.isTextAvailable()) {
211: if (currentTag.getTagName().equals(AML_TEXT)) {
212: currentTag.setAttribute(ATTR_TEXT, state.getText());
213: element = currentTag;
214: } else {
215: // If element is not AmlText, create a new AmlText element
216: // with the provided text
217: element = createAmlTextElement(state.getText(), state);
218: }
219:
220: state.clearText();
221: }
222:
223: // If a following line break is required,
224: // add an AmlBr to the current output container
225: // The AmlText element also needs to appended here,
226: // so that ordering is proper - AmlBr after AmlText,
227: // which means that some of the functionality of
228: // HtmlParserCallback.endTag is duplicated here
229: if (state.getTextTagContext().hasFollowingLineBreak()) {
230: if (element != currentTag && element != null) {
231: GenericHtmlParserCallback.appendChildToOutputContainer(
232: state, element);
233: state.setCurrentOutputTag(element);
234: }
235:
236: Element amlBr = AmlBrTagProcessor.createAmlBrElement(state);
237: GenericHtmlParserCallback.appendChildToOutputContainer(
238: state, amlBr);
239:
240: // Since we've already appended it to the output
241: // container, we don't want HtmlParserCallback doing
242: // the same
243: element = null;
244: }
245:
246: // Rollback the text style from ParserState
247: state.rollbackTextTagContext();
248:
249: // This should rollback the AmlListItem created
250: // for the dt tag in startTag
251: if (tag.equals(TextTag.DD.getTagName())) {
252: state.rollbackOutputContainerTag();
253: }
254:
255: return element;
256: }
257:
258: /* (non-Javadoc)
259: * @see com.sun.portal.wireless.htmlconversion.TagProcessor#canHaveChildren()
260: */
261: public boolean canHaveChildren(ParserState state) {
262: return false;
263: }
264:
265: /**
266: * Returns a new AmlText element with the specified text and formatting
267: * based on the current text style obtained from ParserState
268: *
269: * @param text
270: * @param state
271: * @return
272: */
273: public static Element createAmlTextElement(String text,
274: ParserState state) {
275: Element element = state.newElement(AML_TEXT);
276:
277: if (text != null) {
278: element.setAttribute(ATTR_TEXT, text);
279: }
280:
281: TextTag style = state.getTextTagContext();
282:
283: // Add formatting from the style to AmlText
284: if (style.getTextSize() != null
285: && !style.getTextSize()
286: .equals(TextTag.TEXT_SIZE_NORMAL)) {
287: element.setAttribute(ATTR_TEXTSIZE, style.getTextSize());
288: }
289:
290: if (style.getHalign() != null) {
291: element.setAttribute(ATTR_HALIGN, style.getHalign());
292: }
293:
294: if (style.getValign() != null) {
295: element.setAttribute(ATTR_VALIGN, style.getValign());
296: }
297:
298: if (style.isBold()) {
299: element.setAttribute(ATTR_BOLD, VAL_TRUE);
300: }
301:
302: if (style.isItalics()) {
303: element.setAttribute(ATTR_ITALICS, VAL_TRUE);
304: }
305:
306: if (style.isUnderlined()) {
307: element.setAttribute(ATTR_UNDERLINE, VAL_TRUE);
308: }
309:
310: if (style.getColour() != null) {
311: element.setAttribute(ATTR_COLOR, style.getColour());
312: }
313:
314: if (style.getFont() != null) {
315: element.setAttribute(ATTR_FONT, style.getFont());
316: }
317:
318: return element;
319: }
320:
321: }
|