001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.util;
029:
030: import java.awt.Color;
031: import java.awt.GraphicsEnvironment;
032: import java.awt.font.TextAttribute;
033: import java.io.IOException;
034: import java.io.StringReader;
035: import java.text.AttributedCharacterIterator;
036: import java.util.HashMap;
037: import java.util.List;
038: import java.util.Map;
039: import java.util.StringTokenizer;
040:
041: import javax.xml.parsers.DocumentBuilder;
042: import javax.xml.parsers.DocumentBuilderFactory;
043: import javax.xml.parsers.ParserConfigurationException;
044:
045: import net.sf.jasperreports.engine.JRRuntimeException;
046: import net.sf.jasperreports.engine.xml.JRXmlConstants;
047:
048: import org.w3c.dom.Document;
049: import org.w3c.dom.NamedNodeMap;
050: import org.w3c.dom.Node;
051: import org.w3c.dom.NodeList;
052: import org.xml.sax.InputSource;
053: import org.xml.sax.SAXException;
054:
055: /**
056: * @author Teodor Danciu (teodord@users.sourceforge.net)
057: * @version $Id: JRStyledTextParser.java 1734 2007-06-01 14:55:03Z shertage $
058: */
059: public class JRStyledTextParser {
060:
061: /**
062: *
063: */
064: private static final String ROOT_START = "<st>";
065: private static final String ROOT_END = "</st>";
066: private static final String NODE_style = "style";
067: private static final String NODE_bold = "b";
068: private static final String NODE_italic = "i";
069: private static final String NODE_underline = "u";
070: private static final String NODE_sup = "sup";
071: private static final String NODE_sub = "sub";
072: private static final String NODE_font = "font";
073: private static final String NODE_br = "br";
074: private static final String NODE_li = "li";
075: private static final String ATTRIBUTE_fontName = "fontName";
076: private static final String ATTRIBUTE_fontFace = "face";
077: private static final String ATTRIBUTE_color = "color";
078: private static final String ATTRIBUTE_size = "size";
079: private static final String ATTRIBUTE_isBold = "isBold";
080: private static final String ATTRIBUTE_isItalic = "isItalic";
081: private static final String ATTRIBUTE_isUnderline = "isUnderline";
082: private static final String ATTRIBUTE_isStrikeThrough = "isStrikeThrough";
083: private static final String ATTRIBUTE_forecolor = "forecolor";
084: private static final String ATTRIBUTE_backcolor = "backcolor";
085: private static final String ATTRIBUTE_pdfFontName = "pdfFontName";
086: private static final String ATTRIBUTE_pdfEncoding = "pdfEncoding";
087: private static final String ATTRIBUTE_isPdfEmbedded = "isPdfEmbedded";
088:
089: private static final String SPACE = " ";
090: private static final String EQUAL_QUOTE = "=\"";
091: private static final String QUOTE = "\"";
092: private static final String SHARP = "#";
093: private static final String LESS = "<";
094: private static final String LESS_SLASH = "</";
095: private static final String GREATER = ">";
096:
097: /**
098: *
099: */
100: private DocumentBuilder documentBuilder = null;
101:
102: /**
103: *
104: */
105: public JRStyledTextParser() {
106: try {
107: DocumentBuilderFactory factory = DocumentBuilderFactory
108: .newInstance();
109: documentBuilder = factory.newDocumentBuilder();
110: } catch (ParserConfigurationException e) {
111: throw new JRRuntimeException(e);
112: }
113: }
114:
115: /**
116: *
117: */
118: public JRStyledText parse(Map attributes, String text)
119: throws SAXException {
120: JRStyledText styledText = new JRStyledText();
121:
122: Document document = null;
123:
124: try {
125: document = documentBuilder.parse(new InputSource(
126: new StringReader(ROOT_START + text + ROOT_END)));
127: } catch (IOException e) {
128: throw new JRRuntimeException(e);
129: }
130:
131: parseStyle(styledText, document.getDocumentElement());
132:
133: styledText.addRun(new JRStyledText.Run(attributes, 0,
134: styledText.length()));
135:
136: return styledText;
137: }
138:
139: /**
140: *
141: */
142: public String write(Map parentAttrs,
143: AttributedCharacterIterator iterator, String text) {
144: StringBuffer sbuffer = new StringBuffer();
145:
146: int runLimit = 0;
147:
148: while (runLimit < iterator.getEndIndex()
149: && (runLimit = iterator.getRunLimit()) <= iterator
150: .getEndIndex()) {
151: String chunk = text
152: .substring(iterator.getIndex(), runLimit);
153: Map attrs = iterator.getAttributes();
154:
155: StringBuffer styleBuffer = writeStyleAttributes(
156: parentAttrs, attrs);
157: if (styleBuffer.length() > 0) {
158: sbuffer.append(LESS);
159: sbuffer.append(NODE_style);
160: sbuffer.append(styleBuffer.toString());
161: sbuffer.append(GREATER);
162: writeChunk(sbuffer, parentAttrs, attrs, chunk);
163: sbuffer.append(LESS_SLASH);
164: sbuffer.append(NODE_style);
165: sbuffer.append(GREATER);
166: } else {
167: writeChunk(sbuffer, parentAttrs, attrs, chunk);
168: }
169:
170: iterator.setIndex(runLimit);
171: }
172:
173: return sbuffer.toString();
174: }
175:
176: /**
177: *
178: */
179: public void writeChunk(StringBuffer sbuffer, Map parentAttrs,
180: Map attrs, String chunk) {
181: Object value = attrs.get(TextAttribute.SUPERSCRIPT);
182: Object oldValue = parentAttrs.get(TextAttribute.SUPERSCRIPT);
183:
184: boolean isSuper = false;
185: boolean isSub = false;
186:
187: if (value != null && !value.equals(oldValue)) {
188: isSuper = TextAttribute.SUPERSCRIPT_SUPER.equals(value);
189: isSub = TextAttribute.SUPERSCRIPT_SUB.equals(value);
190: }
191:
192: if (isSuper || isSub) {
193: String node = isSuper ? NODE_sup : NODE_sub;
194: sbuffer.append(LESS);
195: sbuffer.append(node);
196: sbuffer.append(GREATER);
197: sbuffer.append(JRStringUtil.xmlEncode(chunk));
198: sbuffer.append(LESS_SLASH);
199: sbuffer.append(node);
200: sbuffer.append(GREATER);
201: } else {
202: sbuffer.append(JRStringUtil.xmlEncode(chunk));
203: }
204: }
205:
206: /**
207: *
208: */
209: private void parseStyle(JRStyledText styledText, Node parentNode)
210: throws SAXException {
211: NodeList nodeList = parentNode.getChildNodes();
212: for (int i = 0; i < nodeList.getLength(); i++) {
213: Node node = nodeList.item(i);
214: if (node.getNodeType() == Node.TEXT_NODE) {
215: styledText.append(node.getNodeValue());
216: } else if (node.getNodeType() == Node.ELEMENT_NODE
217: && NODE_style.equals(node.getNodeName())) {
218: NamedNodeMap nodeAttrs = node.getAttributes();
219:
220: Map styleAttrs = new HashMap();
221:
222: if (nodeAttrs.getNamedItem(ATTRIBUTE_fontName) != null) {
223: styleAttrs.put(TextAttribute.FAMILY, nodeAttrs
224: .getNamedItem(ATTRIBUTE_fontName)
225: .getNodeValue());
226: }
227:
228: if (nodeAttrs.getNamedItem(ATTRIBUTE_isBold) != null) {
229: styleAttrs.put(TextAttribute.WEIGHT, Boolean
230: .valueOf(
231: nodeAttrs.getNamedItem(
232: ATTRIBUTE_isBold)
233: .getNodeValue())
234: .booleanValue() ? TextAttribute.WEIGHT_BOLD
235: : TextAttribute.WEIGHT_REGULAR);
236: }
237:
238: if (nodeAttrs.getNamedItem(ATTRIBUTE_isItalic) != null) {
239: styleAttrs
240: .put(
241: TextAttribute.POSTURE,
242: Boolean.valueOf(
243: nodeAttrs.getNamedItem(
244: ATTRIBUTE_isItalic)
245: .getNodeValue())
246: .booleanValue() ? TextAttribute.POSTURE_OBLIQUE
247: : TextAttribute.POSTURE_REGULAR);
248: }
249:
250: if (nodeAttrs.getNamedItem(ATTRIBUTE_isUnderline) != null) {
251: styleAttrs
252: .put(
253: TextAttribute.UNDERLINE,
254: Boolean
255: .valueOf(
256: nodeAttrs
257: .getNamedItem(
258: ATTRIBUTE_isUnderline)
259: .getNodeValue())
260: .booleanValue() ? TextAttribute.UNDERLINE_ON
261: : null);
262: }
263:
264: if (nodeAttrs.getNamedItem(ATTRIBUTE_isStrikeThrough) != null) {
265: styleAttrs
266: .put(
267: TextAttribute.STRIKETHROUGH,
268: Boolean
269: .valueOf(
270: nodeAttrs
271: .getNamedItem(
272: ATTRIBUTE_isStrikeThrough)
273: .getNodeValue())
274: .booleanValue() ? TextAttribute.STRIKETHROUGH_ON
275: : null);
276: }
277:
278: if (nodeAttrs.getNamedItem(ATTRIBUTE_size) != null) {
279: styleAttrs.put(TextAttribute.SIZE, new Float(
280: nodeAttrs.getNamedItem(ATTRIBUTE_size)
281: .getNodeValue()));
282: }
283:
284: if (nodeAttrs.getNamedItem(ATTRIBUTE_pdfFontName) != null) {
285: styleAttrs.put(JRTextAttribute.PDF_FONT_NAME,
286: nodeAttrs.getNamedItem(
287: ATTRIBUTE_pdfFontName)
288: .getNodeValue());
289: }
290:
291: if (nodeAttrs.getNamedItem(ATTRIBUTE_pdfEncoding) != null) {
292: styleAttrs.put(JRTextAttribute.PDF_ENCODING,
293: nodeAttrs.getNamedItem(
294: ATTRIBUTE_pdfEncoding)
295: .getNodeValue());
296: }
297:
298: if (nodeAttrs.getNamedItem(ATTRIBUTE_isPdfEmbedded) != null) {
299: styleAttrs.put(JRTextAttribute.IS_PDF_EMBEDDED,
300: Boolean.valueOf(nodeAttrs.getNamedItem(
301: ATTRIBUTE_isPdfEmbedded)
302: .getNodeValue()));
303: }
304:
305: if (nodeAttrs.getNamedItem(ATTRIBUTE_forecolor) != null) {
306: Color color = JRXmlConstants.getColor(nodeAttrs
307: .getNamedItem(ATTRIBUTE_forecolor)
308: .getNodeValue(), Color.black);
309: styleAttrs.put(TextAttribute.FOREGROUND, color);
310: }
311:
312: if (nodeAttrs.getNamedItem(ATTRIBUTE_backcolor) != null) {
313: Color color = JRXmlConstants.getColor(nodeAttrs
314: .getNamedItem(ATTRIBUTE_backcolor)
315: .getNodeValue(), Color.black);
316: styleAttrs.put(TextAttribute.BACKGROUND, color);
317: }
318:
319: int startIndex = styledText.length();
320:
321: parseStyle(styledText, node);
322:
323: styledText.addRun(new JRStyledText.Run(styleAttrs,
324: startIndex, styledText.length()));
325: } else if (node.getNodeType() == Node.ELEMENT_NODE
326: && NODE_bold.equalsIgnoreCase(node.getNodeName())) {
327: Map styleAttrs = new HashMap();
328: styleAttrs.put(TextAttribute.WEIGHT,
329: TextAttribute.WEIGHT_BOLD);
330:
331: int startIndex = styledText.length();
332:
333: parseStyle(styledText, node);
334:
335: styledText.addRun(new JRStyledText.Run(styleAttrs,
336: startIndex, styledText.length()));
337: } else if (node.getNodeType() == Node.ELEMENT_NODE
338: && NODE_italic.equalsIgnoreCase(node.getNodeName())) {
339: Map styleAttrs = new HashMap();
340: styleAttrs.put(TextAttribute.POSTURE,
341: TextAttribute.POSTURE_OBLIQUE);
342:
343: int startIndex = styledText.length();
344:
345: parseStyle(styledText, node);
346:
347: styledText.addRun(new JRStyledText.Run(styleAttrs,
348: startIndex, styledText.length()));
349: } else if (node.getNodeType() == Node.ELEMENT_NODE
350: && NODE_underline.equalsIgnoreCase(node
351: .getNodeName())) {
352: Map styleAttrs = new HashMap();
353: styleAttrs.put(TextAttribute.UNDERLINE,
354: TextAttribute.UNDERLINE_ON);
355:
356: int startIndex = styledText.length();
357:
358: parseStyle(styledText, node);
359:
360: styledText.addRun(new JRStyledText.Run(styleAttrs,
361: startIndex, styledText.length()));
362: } else if (node.getNodeType() == Node.ELEMENT_NODE
363: && NODE_sup.equalsIgnoreCase(node.getNodeName())) {
364: Map styleAttrs = new HashMap();
365: styleAttrs.put(TextAttribute.SUPERSCRIPT,
366: TextAttribute.SUPERSCRIPT_SUPER);
367:
368: int startIndex = styledText.length();
369:
370: parseStyle(styledText, node);
371:
372: styledText.addRun(new JRStyledText.Run(styleAttrs,
373: startIndex, styledText.length()));
374: } else if (node.getNodeType() == Node.ELEMENT_NODE
375: && NODE_sub.equalsIgnoreCase(node.getNodeName())) {
376: Map styleAttrs = new HashMap();
377: styleAttrs.put(TextAttribute.SUPERSCRIPT,
378: TextAttribute.SUPERSCRIPT_SUB);
379:
380: int startIndex = styledText.length();
381:
382: parseStyle(styledText, node);
383:
384: styledText.addRun(new JRStyledText.Run(styleAttrs,
385: startIndex, styledText.length()));
386: } else if (node.getNodeType() == Node.ELEMENT_NODE
387: && NODE_font.equalsIgnoreCase(node.getNodeName())) {
388: NamedNodeMap nodeAttrs = node.getAttributes();
389:
390: Map styleAttrs = new HashMap();
391:
392: if (nodeAttrs.getNamedItem(ATTRIBUTE_fontFace) != null) {
393: styleAttrs.put(JRTextAttribute.HTML_FONT_FACE,
394: nodeAttrs.getNamedItem(ATTRIBUTE_fontFace)
395: .getNodeValue());
396: }
397: if (nodeAttrs.getNamedItem(ATTRIBUTE_size) != null) {
398: styleAttrs.put(TextAttribute.SIZE, new Float(
399: nodeAttrs.getNamedItem(ATTRIBUTE_size)
400: .getNodeValue()));
401: }
402:
403: if (nodeAttrs.getNamedItem(ATTRIBUTE_color) != null) {
404: Color color = JRXmlConstants.getColor(nodeAttrs
405: .getNamedItem(ATTRIBUTE_color)
406: .getNodeValue(), Color.black);
407: styleAttrs.put(TextAttribute.FOREGROUND, color);
408: }
409:
410: if (nodeAttrs.getNamedItem(ATTRIBUTE_fontFace) != null) {
411: String[] fontList = GraphicsEnvironment
412: .getLocalGraphicsEnvironment()
413: .getAvailableFontFamilyNames();
414: String fontFaces = nodeAttrs.getNamedItem(
415: ATTRIBUTE_fontFace).getNodeValue();
416:
417: StringTokenizer t = new StringTokenizer(fontFaces,
418: ",");
419: label: while (t.hasMoreTokens()) {
420: String face = t.nextToken().trim();
421: for (int j = 0; j < fontList.length; j++)
422: if (fontList[j].equals(face)) {
423: styleAttrs.put(TextAttribute.FAMILY,
424: face);
425: break label;
426: }
427: }
428: }
429: int startIndex = styledText.length();
430:
431: parseStyle(styledText, node);
432:
433: styledText.addRun(new JRStyledText.Run(styleAttrs,
434: startIndex, styledText.length()));
435:
436: } else if (node.getNodeType() == Node.ELEMENT_NODE
437: && NODE_br.equalsIgnoreCase(node.getNodeName())) {
438: styledText.append("\n");
439:
440: int startIndex = styledText.length();
441: resizeRuns(styledText.getRuns(), startIndex, 1);
442:
443: parseStyle(styledText, node);
444: styledText.addRun(new JRStyledText.Run(new HashMap(),
445: startIndex, styledText.length()));
446:
447: if (startIndex < styledText.length()) {
448: styledText.append("\n");
449: resizeRuns(styledText.getRuns(), startIndex, 1);
450: }
451: } else if (node.getNodeType() == Node.ELEMENT_NODE
452: && NODE_li.equalsIgnoreCase(node.getNodeName())) {
453: String tmpText = styledText.getText();
454: if (tmpText.length() > 0 && !tmpText.endsWith("\n")) {
455: styledText.append("\n");
456: }
457: styledText.append(" \u2022 ");
458:
459: int startIndex = styledText.length();
460: resizeRuns(styledText.getRuns(), startIndex, 1);
461: parseStyle(styledText, node);
462: styledText.addRun(new JRStyledText.Run(new HashMap(),
463: startIndex, styledText.length()));
464:
465: // if the text in the next node does not start with a '\n', or
466: // if the next node is not a <li /> one, we have to append a new line
467: Node nextNode = node.getNextSibling();
468: String textContent = getFirstTextOccurence(nextNode);
469: if (nextNode != null
470: && !((nextNode.getNodeType() == Node.ELEMENT_NODE
471: && NODE_li.equalsIgnoreCase(nextNode
472: .getNodeName()) || (textContent != null && textContent
473: .startsWith("\n"))))) {
474: styledText.append("\n");
475: resizeRuns(styledText.getRuns(), startIndex, 1);
476: }
477: } else if (node.getNodeType() == Node.ELEMENT_NODE) {
478: String nodeName = "<" + node.getNodeName() + ">";
479: throw new SAXException("Tag " + nodeName
480: + " is not a valid styled text tag.");
481: }
482: }
483: }
484:
485: /**
486: *
487: */
488: private void resizeRuns(List runs, int startIndex, int count) {
489: for (int j = 0; j < runs.size(); j++) {
490: JRStyledText.Run run = (JRStyledText.Run) runs.get(j);
491: if (run.startIndex <= startIndex
492: && run.endIndex > startIndex - count)
493: run.endIndex += count;
494: }
495: }
496:
497: /**
498: *
499: */
500: private StringBuffer writeStyleAttributes(Map parentAttrs, Map attrs) {
501: StringBuffer sbuffer = new StringBuffer();
502:
503: Object value = attrs.get(TextAttribute.FAMILY);
504: Object oldValue = parentAttrs.get(TextAttribute.FAMILY);
505:
506: if (value != null && !value.equals(oldValue)) {
507: sbuffer.append(SPACE);
508: sbuffer.append(ATTRIBUTE_fontName);
509: sbuffer.append(EQUAL_QUOTE);
510: sbuffer.append(value);
511: sbuffer.append(QUOTE);
512: }
513:
514: value = attrs.get(TextAttribute.WEIGHT);
515: oldValue = parentAttrs.get(TextAttribute.WEIGHT);
516:
517: if (value != null && !value.equals(oldValue)) {
518: sbuffer.append(SPACE);
519: sbuffer.append(ATTRIBUTE_isBold);
520: sbuffer.append(EQUAL_QUOTE);
521: sbuffer.append(value.equals(TextAttribute.WEIGHT_BOLD));
522: sbuffer.append(QUOTE);
523: }
524:
525: value = attrs.get(TextAttribute.POSTURE);
526: oldValue = parentAttrs.get(TextAttribute.POSTURE);
527:
528: if (value != null && !value.equals(oldValue)) {
529: sbuffer.append(SPACE);
530: sbuffer.append(ATTRIBUTE_isItalic);
531: sbuffer.append(EQUAL_QUOTE);
532: sbuffer.append(value.equals(TextAttribute.POSTURE_OBLIQUE));
533: sbuffer.append(QUOTE);
534: }
535:
536: value = attrs.get(TextAttribute.UNDERLINE);
537: oldValue = parentAttrs.get(TextAttribute.UNDERLINE);
538:
539: if ((value == null && oldValue != null)
540: || (value != null && !value.equals(oldValue))) {
541: sbuffer.append(SPACE);
542: sbuffer.append(ATTRIBUTE_isUnderline);
543: sbuffer.append(EQUAL_QUOTE);
544: sbuffer.append(value != null);
545: sbuffer.append(QUOTE);
546: }
547:
548: value = attrs.get(TextAttribute.STRIKETHROUGH);
549: oldValue = parentAttrs.get(TextAttribute.STRIKETHROUGH);
550:
551: if ((value == null && oldValue != null)
552: || (value != null && !value.equals(oldValue))) {
553: sbuffer.append(SPACE);
554: sbuffer.append(ATTRIBUTE_isStrikeThrough);
555: sbuffer.append(EQUAL_QUOTE);
556: sbuffer.append(value != null);
557: sbuffer.append(QUOTE);
558: }
559:
560: value = attrs.get(TextAttribute.SIZE);
561: oldValue = parentAttrs.get(TextAttribute.SIZE);
562:
563: if (value != null && !value.equals(oldValue)) {
564: sbuffer.append(SPACE);
565: sbuffer.append(ATTRIBUTE_size);
566: sbuffer.append(EQUAL_QUOTE);
567: sbuffer.append(((Float) value).intValue());
568: sbuffer.append(QUOTE);
569: }
570:
571: value = attrs.get(JRTextAttribute.PDF_FONT_NAME);
572: oldValue = parentAttrs.get(JRTextAttribute.PDF_FONT_NAME);
573:
574: if (value != null && !value.equals(oldValue)) {
575: sbuffer.append(SPACE);
576: sbuffer.append(ATTRIBUTE_pdfFontName);
577: sbuffer.append(EQUAL_QUOTE);
578: sbuffer.append(value);
579: sbuffer.append(QUOTE);
580: }
581:
582: value = attrs.get(JRTextAttribute.PDF_ENCODING);
583: oldValue = parentAttrs.get(JRTextAttribute.PDF_ENCODING);
584:
585: if (value != null && !value.equals(oldValue)) {
586: sbuffer.append(SPACE);
587: sbuffer.append(ATTRIBUTE_pdfEncoding);
588: sbuffer.append(EQUAL_QUOTE);
589: sbuffer.append(value);
590: sbuffer.append(QUOTE);
591: }
592:
593: value = attrs.get(JRTextAttribute.IS_PDF_EMBEDDED);
594: oldValue = parentAttrs.get(JRTextAttribute.IS_PDF_EMBEDDED);
595:
596: if (value != null && !value.equals(oldValue)) {
597: sbuffer.append(SPACE);
598: sbuffer.append(ATTRIBUTE_isPdfEmbedded);
599: sbuffer.append(EQUAL_QUOTE);
600: sbuffer.append(value);
601: sbuffer.append(QUOTE);
602: }
603:
604: value = attrs.get(TextAttribute.FOREGROUND);
605: oldValue = parentAttrs.get(TextAttribute.FOREGROUND);
606:
607: if (value != null && !value.equals(oldValue)) {
608: sbuffer.append(SPACE);
609: sbuffer.append(ATTRIBUTE_forecolor);
610: sbuffer.append(EQUAL_QUOTE);
611: sbuffer.append(SHARP);
612: sbuffer.append(JRColorUtil.getColorHexa((Color) value));
613: sbuffer.append(QUOTE);
614: }
615:
616: value = attrs.get(TextAttribute.BACKGROUND);
617: oldValue = parentAttrs.get(TextAttribute.BACKGROUND);
618:
619: if (value != null && !value.equals(oldValue)) {
620: sbuffer.append(SPACE);
621: sbuffer.append(ATTRIBUTE_backcolor);
622: sbuffer.append(EQUAL_QUOTE);
623: sbuffer.append(SHARP);
624: sbuffer.append(JRColorUtil.getColorHexa((Color) value));
625: sbuffer.append(QUOTE);
626: }
627:
628: return sbuffer;
629: }
630:
631: /**
632: * The method returns the first text occurence in a given node element
633: * @param node
634: * @return String
635: */
636: private String getFirstTextOccurence(Node node) {
637: if (node != null) {
638: if (node.getNodeValue() != null)
639: return node.getNodeValue();
640: NodeList nodeList = node.getChildNodes();
641: for (int i = 0; i < nodeList.getLength(); i++) {
642: String firstOccurence = getFirstTextOccurence(nodeList
643: .item(i));
644: if (firstOccurence != null)
645: return firstOccurence;
646: }
647: }
648: return null;
649: }
650:
651: }
|