1 /*
2 * Copyright (c) 2001 - 2005 ivata limited.
3 * All rights reserved.
4 * -----------------------------------------------------------------------------
5 * ivata masks may be redistributed under the GNU General Public
6 * License as published by the Free Software Foundation;
7 * version 2 of the License.
8 *
9 * These programs are free software; you can redistribute them and/or
10 * modify them under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; version 2 of the License.
12 *
13 * These programs are distributed in the hope that they will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * See the GNU General Public License in the file LICENSE.txt for more
18 * details.
19 *
20 * If you would like a copy of the GNU General Public License write to
21 *
22 * Free Software Foundation, Inc.
23 * 59 Temple Place - Suite 330
24 * Boston, MA 02111-1307, USA.
25 *
26 *
27 * To arrange commercial support and licensing, contact ivata at
28 * http://www.ivata.com/contact.jsp
29 * -----------------------------------------------------------------------------
30 * $Log: CharacterEntityFormat.java,v $
31 * Revision 1.3 2005/04/11 14:45:38 colinmacleod
32 * Changed HTMLFormat from an abstract class
33 * into an interface.
34 *
35 * Revision 1.2 2005/04/09 18:04:18 colinmacleod
36 * Changed copyright text to GPL v2 explicitly.
37 *
38 * Revision 1.1 2005/01/06 22:41:01 colinmacleod
39 * Moved up a version number.
40 * Changed copyright notices to 2005.
41 * Updated the documentation:
42 * - started working on multiproject:site docu.
43 * - changed the logo.
44 * Added checkstyle and fixed LOADS of style issues.
45 * Added separate thirdparty subproject.
46 * Added struts (in web), util and webgui (in webtheme) from ivata op.
47 *
48 * Revision 1.4 2004/11/03 17:07:21 colinmacleod
49 * Fixed bug in entity matching.
50 *
51 * Revision 1.3 2004/03/21 21:16:37 colinmacleod
52 * Shortened name to ivata op.
53 *
54 * Revision 1.2 2004/02/01 22:07:32 colinmacleod
55 * Added full names to author tags
56 *
57 * Revision 1.1.1.1 2004/01/27 20:59:47 colinmacleod
58 * Moved ivata op to SourceForge.
59 *
60 * Revision 1.2 2003/10/15 14:13:39 colin
61 * Fixes for XDoclet.
62 *
63 * Revision 1.3 2003/02/26 08:15:03 colin
64 * Fixed bug in append routine.
65 *
66 * Revision 1.2 2003/02/26 08:13:43 colin
67 * added toString to entity StringBuffer - not supported in JDK 1.3
68 *
69 * Revision 1.1 2003/02/24 19:33:32 colin
70 * Moved to new subproject.
71 *
72 * Revision 1.5 2003/02/04 17:43:46 colin
73 * copyright notice
74 *
75 * Revision 1.4 2002/09/06 15:08:34 colin
76 * split off the character entity map into a new file
77 *
78 * Revision 1.3 2002/09/04 08:10:36 colin
79 * fixed bug when entities are converted by browser
80 *
81 * Revision 1.1 2002/06/21 11:58:37 colin
82 * restructured com.ivata.mask.jsp into
83 * format, JavaScript, theme and tree.
84 * -----------------------------------------------------------------------------
85 */
86 package com.ivata.mask.web.format;
87 /***
88 * Convert characters to their HTML character entity equivalents.
89 *
90 * @since ivata masks 0.4 (2002-06-19)
91 * @author Colin MacLeod
92 * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
93 * @version $Revision: 1.3 $
94 */
95 public class CharacterEntityFormat implements HTMLFormat {
96 /***
97 * Maintain the mapping via this translation array.
98 */
99 static final String[][] ENTITIES = {
100 // quotation mark = APL quote
101 // NOTE: JBuilder compiler wouldn't accept the Unicode value here
102 // (\u0022): probably an internal compiler problem with the string
103 // quotes
104 {"\"", "quot" }, //\u0022
105 {"\"", "#34"}, //\u0022
106 // ampersand
107 {"\u0026", "amp"}, {"\u0026", "#38"}, {"&", "amp"},
108 {"\u0027", "#39"},
109 // less-than sign
110 {"\u003C", "lt"}, {"\u003C", "#60"}, {"<", "lt"},
111 // greater-than sign
112 {"\u003E", "gt"}, {"\u003E", "#62"}, {">", "gt"},
113 // Latin capital ligature OE
114 {"\u0152", "OElig"}, {"\u0152", "#338"},
115 // Latin small ligature oe
116 {"\u0153", "oelig"}, {"\u0153", "#339"},
117 // Latin capital letter S with caron
118 {"\u0160", "Scaron"}, {"\u0160", "#352"},
119 // Latin small letter s with caron
120 {"\u0161", "scaron"}, {"\u0161", "#353"},
121 // Latin capital letter Y with diaeresis
122 {"\u0178", "Yuml"}, {"\u0178", "#376"},
123 // Latin small f with hook = function = florin
124 {"\u0192", "fnof"}, {"\u0192", "#402"},
125 // modifier letter circumflex accent
126 {"\u02C6", "circ"}, {"\u02C6", "#710"},
127 // small tilde
128 {"\u02DC", "tilde"}, {"\u02DC", "#732"},
129 // greek capital letter alpha
130 {"\u0391", "Alpha"}, {"\u0391", "#913"},
131 // greek capital letter beta
132 {"\u0392", "Beta"}, {"\u0392", "#914"},
133 // greek capital letter gamma
134 {"\u0393", "Gamma"}, {"\u0393", "#915"},
135 // greek capital letter delta
136 {"\u0394", "Delta"}, {"\u0394", "#916"},
137 // greek capital letter epsilon
138 {"\u0395", "Epsilon"}, {"\u0395", "#917"},
139 // greek capital letter zeta
140 {"\u0396", "Zeta"}, {"\u0396", "#918"},
141 // greek capital letter eta
142 {"\u0397", "Eta"}, {"\u0397", "#919"},
143 // greek capital letter theta
144 {"\u0398", "Theta"}, {"\u0398", "#920"},
145 // greek capital letter iota
146 {"\u0399", "Iota"}, {"\u0399", "#921"},
147 // greek capital letter kappa
148 {"\u039A", "Kappa"}, {"\u039A", "#922"},
149 // greek capital letter lambda
150 {"\u039B", "Lambda"}, {"\u039B", "#923"},
151 // greek capital letter mu
152 {"\u039C", "Mu"}, {"\u039C", "#924"},
153 // greek capital letter nu
154 {"\u039D", "Nu"}, {"\u039D", "#925"},
155 // greek capital letter xi
156 {"\u039E", "Xi"}, {"\u039E", "#926"},
157 // greek capital letter omicron
158 {"\u039F", "Omicron"}, {"\u039F", "#927"},
159 // greek capital letter pi
160 {"\u03A0", "Pi"}, {"\u03A0", "#928"},
161 // greek capital letter rho
162 {"\u03A1", "Rho"}, {"\u03A1", "#929"},
163 // greek capital letter sigma
164 {"\u03A3", "Sigma"}, {"\u03A3", "#931"},
165 // greek capital letter tau
166 {"\u03A4", "Tau"}, {"\u03A4", "#932"},
167 // greek capital letter upsilon
168 {"\u03A5", "Upsilon"}, {"\u03A5", "#933"},
169 // greek capital letter phi
170 {"\u03A6", "Phi"}, {"\u03A6", "#934"},
171 // greek capital letter chi
172 {"\u03A7", "Chi"}, {"\u03A7", "#935"},
173 // greek capital letter psi
174 {"\u03A8", "Psi"}, {"\u03A8", "#936"},
175 // greek capital letter omega
176 {"\u03A9", "Omega"}, {"\u03A9", "#937"},
177 // greek small letter alpha
178 {"\u03B1", "alpha"}, {"\u03B1", "#945"},
179 // greek small letter beta
180 {"\u03B2", "beta"}, {"\u03B2", "#946"},
181 // greek small letter gamma
182 {"\u03B3", "gamma"}, {"\u03B3", "#947"},
183 // greek small letter delta
184 {"\u03B4", "delta"}, {"\u03B4", "#948"},
185 // greek small letter epsilon
186 {"\u03B5", "epsilon"}, {"\u03B5", "#949"},
187 // greek small letter zeta
188 {"\u03B6", "zeta"}, {"\u03B6", "#950"},
189 // greek small letter eta
190 {"\u03B7", "eta"}, {"\u03B7", "#951"},
191 // greek small letter theta
192 {"\u03B8", "theta"}, {"\u03B8", "#952"},
193 // greek small letter iota
194 {"\u03B9", "iota"}, {"\u03B9", "#953"},
195 // greek small letter kappa
196 {"\u03BA", "kappa"}, {"\u03BA", "#954"},
197 // greek small letter lambda
198 {"\u03BB", "lambda"}, {"\u03BB", "#955"},
199 // greek small letter mu
200 {"\u03BC", "mu"}, {"\u03BC", "#956"},
201 // greek small letter nu
202 {"\u03BD", "nu"}, {"\u03BD", "#957"},
203 // greek small letter xi
204 {"\u03BE", "xi"}, {"\u03BE", "#958"},
205 // greek small letter omicron
206 {"\u03BF", "omicron"}, {"\u03BF", "#959"},
207 // greek small letter pi
208 {"\u03C0", "pi"}, {"\u03C0", "#960"},
209 // greek small letter rho
210 {"\u03C1", "rho"}, {"\u03C1", "#961"},
211 // greek small letter final sigma
212 {"\u03C2", "sigmaf"}, {"\u03C2", "#962"},
213 // greek small letter sigma
214 {"\u03C3", "sigma"}, {"\u03C3", "#963"},
215 // greek small letter tau
216 {"\u03C4", "tau"}, {"\u03C4", "#964"},
217 // greek small letter upsilon
218 {"\u03C5", "upsilon"}, {"\u03C5", "#965"},
219 // greek small letter phi
220 {"\u03C6", "phi"}, {"\u03C6", "#966"},
221 // greek small letter chi
222 {"\u03C7", "chi"}, {"\u03C7", "#967"},
223 // greek small letter psi
224 {"\u03C8", "psi"}, {"\u03C8", "#968"},
225 // greek small letter omega
226 {"\u03C9", "omega"}, {"\u03C9", "#969"},
227 // greek small letter theta symbol
228 {"\u03D1", "thetasym"}, {"\u03D1", "#977"},
229 // greek upsilon with hook symbol
230 {"\u03D2", "upsih"}, {"\u03D2", "#978"},
231 // greek pi symbol
232 {"\u03D6", "piv"}, {"\u03D6", "#982"},
233 // en space
234 {"\u2002", "ensp"}, {"\u2002", "#8194"},
235 // em space
236 {"\u2003", "emsp"}, {"\u2003", "#8195"},
237 // thin space
238 {"\u2009", "thinsp"}, {"\u2009", "#8201"},
239 // zero width non-joiner
240 {"\u200C", "zwnj"}, {"\u200C", "#8204"},
241 // zero width joiner
242 {"\u200D", "zwj"}, {"\u200D", "#8205"},
243 // left-to-right mark
244 {"\u200E", "lrm"}, {"\u200E", "#8206"},
245 // right-to-left mark
246 {"\u200F", "rlm"}, {"\u200F", "#8207"},
247 // en dash
248 {"\u2013", "ndash"}, {"\u2013", "#8211"},
249 // em dash
250 {"\u2014", "mdash"}, {"\u2014", "#8212"},
251 // left single quotation mark
252 {"\u2018", "lsquo"}, {"\u2018", "#8216"},
253 // right single quotation mark
254 {"\u2019", "rsquo"}, {"\u2019", "#8217"},
255 // single low-9 quotation mark
256 {"\u201A", "sbquo"}, {"\u201A", "#8218"},
257 // left double quotation mark
258 {"\u201C", "ldquo"}, {"\u201C", "#8220"},
259 // right double quotation mark
260 {"\u201D", "rdquo"}, {"\u201D", "#8221"},
261 // double low-9 quotation mark
262 {"\u201E", "bdquo"}, {"\u201E", "#8222"},
263 // dagger
264 {"\u2020", "dagger"}, {"\u2020", "#8224"},
265 // double dagger
266 {"\u2021", "Dagger"}, {"\u2021", "#8225"},
267 // bullet = black small circle
268 {"\u2022", "bull"}, {"\u2022", "#8226"},
269 // horizontal ellipsis = three dot leader
270 {"\u2026", "hellip"}, {"\u2026", "#8230"},
271 // per mille sign
272 {"\u2030", "permil"}, {"\u2030", "#8240"},
273 // double prime = seconds = inches
274 {"\u2033", "Prime"}, {"\u2033", "#8243"},
275 // single left-pointing angle quotation mark
276 {"\u2039", "lsaquo"}, {"\u2039", "#8249"},
277 // single right-pointing angle quotation mark
278 {"\u203A", "rsaquo"}, {"\u203A", "#8250"},
279 // prime = minutes = feet
280 {"\u2032", "prime"}, {"\u2032", "#8242"},
281 // overline = spacing overscore
282 {"\u203E", "oline"}, {"\u203E", "#8254"},
283 // fraction slash
284 {"\u2044", "frasl"}, {"\u2044", "#8260"},
285 // euro sign
286 {"\u20AC", "euro"}, {"\u20AC", "#8364"},
287 // script capital P = power set = Weierstrass p
288 {"\u2118", "weierp"}, {"\u2118", "#8472"},
289 // blackletter capital I = imaginary part
290 {"\u2111", "image"}, {"\u2111", "#8465"},
291 // blackletter capital R = real part symbol
292 {"\u211C", "real"}, {"\u211C", "#8476"},
293 // trade mark sign
294 {"\u2122", "trade"}, {"\u2122", "#8482"},
295 // alef symbol = first transfinite cardinal
296 {"\u2135", "alefsym"}, {"\u2135", "#8501"},
297 // leftwards arrow
298 {"\u2190", "larr"}, {"\u2190", "#8592"},
299 // upwards arrow
300 {"\u2191", "uarr"}, {"\u2191", "#8593"},
301 // rightwards arrow
302 {"\u2192", "rarr"}, {"\u2192", "#8594"},
303 // downwards arrow
304 {"\u2193", "darr"}, {"\u2193", "#8595"},
305 // left right arrow
306 {"\u2194", "harr"}, {"\u2194", "#8596"},
307 // downwards arrow with corner leftwards = carriage return
308 {"\u21B5", "crarr"}, {"\u21B5", "#8629"},
309 // leftwards double arrow
310 {"\u21D0", "lArr"}, {"\u21D0", "#8656"},
311 // upwards double arrow
312 {"\u21D1", "uArr"}, {"\u21D1", "#8657"},
313 // rightwards double arrow
314 {"\u21D2", "rArr"}, {"\u21D2", "#8658"},
315 // downwards double arrow
316 {"\u21D3", "hArr"}, {"\u21D3", "#8659"},
317 // left right double arrow
318 {"\u21D4", "hArr"}, {"\u21D4", "#8660"},
319 // for all
320 {"\u2200", "forall"}, {"\u2200", "#8704"},
321 // partial differential
322 {"\u2202", "part"}, {"\u2202", "#8706"},
323 // there exists
324 {"\u2203", "exist"}, {"\u2203", "#8707"},
325 // empty set = null set = diameter
326 {"\u2205", "empty"}, {"\u2205", "#8709"},
327 // nabla = backward difference
328 {"\u2207", "nabla"}, {"\u2207", "#8711"},
329 // element of
330 {"\u2208", "isin"}, {"\u2208", "#8712"},
331 // not an element of
332 {"\u2209", "notin"}, {"\u2209", "#8713"},
333 // contains as member
334 {"\u220B", "ni"}, {"\u220B", "#8715"},
335 // n-ary product = product sign
336 {"\u220F", "prod"}, {"\u220F", "#8719"},
337 // n-ary sumation
338 {"\u2211", "sum"}, {"\u2211", "#8721"},
339 // minus sign
340 {"\u2212", "minus"}, {"\u2212", "#8722"},
341 // asterisk operator
342 {"\u2217", "lowast"}, {"\u2217", "#8727"},
343 // square root = radical sign
344 {"\u221A", "radic"}, {"\u221A", "#8730"},
345 // proportional to
346 {"\u221D", "prop"}, {"\u221D", "#8733"},
347 // infinity
348 {"\u221E", "infin"}, {"\u221E", "#8734"},
349 // angle
350 {"\u2220", "ang"}, {"\u2220", "#8736"},
351 // logical and = wedge
352 {"\u2227", "and"}, {"\u2227", "#8743"},
353 // logical or = vee
354 {"\u2228", "or"}, {"\u2228", "#8744"},
355 // intersection = cap
356 {"\u2229", "cap"}, {"\u2229", "#8745"},
357 // union = cup
358 {"\u222A", "cup"}, {"\u222A", "#8746"},
359 // integral
360 {"\u222B", "int"}, {"\u222B", "#8747"},
361 // therefore
362 {"\u2234", "there4"}, {"\u2234", "#8756"},
363 // tilde operator = varies with = similar to
364 {"\u223C", "sim"}, {"\u223C", "#8764"},
365 // approximately equal to
366 {"\u2245", "cong"}, {"\u2245", "#8773"},
367 // almost equal to = asymptotic to
368 {"\u2248", "asymp"}, {"\u2248", "#8776"},
369 // not equal to
370 {"\u2260", "ne"}, {"\u2260", "#8800"},
371 // identical to
372 {"\u2261", "equiv"}, {"\u2261", "#8801"},
373 // less-than or equal to
374 {"\u2264", "le"}, {"\u2264", "#8804"},
375 // greater-than or equal to
376 {"\u2265", "ge"}, {"\u2265", "#8805"},
377 // subset of
378 {"\u2282", "sub"}, {"\u2282", "#8834"},
379 // superset of
380 {"\u2283", "sup"}, {"\u2283", "#8835"},
381 // not a subset of
382 {"\u2284", "nsub"}, {"\u2284", "#8836"},
383 // subset of or equal to
384 {"\u2286", "sube"}, {"\u2286", "#8838"},
385 // superset of or equal to
386 {"\u2287", "supe"}, {"\u2287", "#8839"},
387 // circled plus = direct sum
388 {"\u2295", "oplus"}, {"\u2295", "#8853"},
389 // circled times = vector product
390 {"\u2297", "otimes"}, {"\u2297", "#8855"},
391 // up tack = orthogonal to = perpendicular
392 {"\u22A5", "perp"}, {"\u22A5", "#8869"},
393 // dot operator
394 {"\u22C5", "sdot"}, {"\u22C5", "#8901"},
395 // left ceiling = apl upstile
396 {"\u2308", "lceil"}, {"\u2308", "#8968"},
397 // right ceiling
398 {"\u2309", "rceil"}, {"\u2309", "#8969"},
399 // left floor = apl downstile
400 {"\u230A", "lfloor"}, {"\u230A", "#8970"},
401 // right floor
402 {"\u230B", "rfloor"}, {"\u230B", "#8971"},
403 // left-pointing angle bracket = bra
404 {"\u2329", "lang"}, {"\u2329", "#9001"},
405 // right-pointing angle bracket = ket
406 {"\u232A", "rang"}, {"\u232A", "#9002"},
407 // lozenge
408 {"\u25CA", "loz"}, {"\u25CA", "#9674"},
409 // black spade suit
410 {"\u2660", "spades"}, {"\u2660", "#9824"},
411 // black club suit = shamrock
412 {"\u2663", "clubs"}, {"\u2663", "#9827"},
413 // black heart suit = valentine
414 {"\u2665", "hearts"}, {"\u2665", "#9829"},
415 // black diamond suit
416 {"\u2666", "diams"}, {"\u2666", "#9830"} };
417 /***
418 * This array stores all of the character entities we want to convert.
419 */
420 private static String[] entitiesArray = null;
421 /***
422 * Each character in this array maps to an entity in
423 * <code>entitiesArray</code>.
424 */
425 private static String entityMapString;
426 /***
427 * This is tag is placed after anything which should not be converted. It is
428 * used by other formats.
429 */
430 private static final String KEEP_END = "</KEEP:>";
431 /***
432 * This is tag is placed before anything which should not be converted. It
433 * is used by other formats.
434 */
435 private static final String KEEP_START = "<KEEP:>";
436 /***
437 * Just what it says on the tin - no character entity string can be longer
438 * than this limit.
439 */
440 private static final int MAXIMUM_ENTITY_LENGTH = 15;
441 /***
442 * Refer to {@link #isReverse}.
443 */
444 private boolean reverse = false;
445 /***
446 * <p>
447 * Default constructor.
448 * </p>
449 */
450 public CharacterEntityFormat() {
451 // this will speed up the conversion of HTML entities
452 // we put them into the array of array of strings to make it more
453 // manageable :-)
454 if (entitiesArray == null) {
455 int length = CharacterEntityFormat.ENTITIES.length;
456 StringBuffer temporaryBuffer = new StringBuffer();
457 entitiesArray = new String[length];
458 for (int n = 0; n < length; ++n) {
459 temporaryBuffer.append(CharacterEntityFormat.ENTITIES[n][0]);
460 entitiesArray[n] = "&" + CharacterEntityFormat.ENTITIES[n][1]
461 + ";";
462 // this code can be used to calculate the maximum entity length
463 /*
464 * if (entities[n][1].length() > MAXIMUM_ENTITY_LENGTH) {
465 * MAXIMUM_ENTITY_LENGTH = entities[n][1].length(); }
466 */
467 }
468 entityMapString = temporaryBuffer.toString();
469 }
470 }
471 /***
472 * <p>
473 * Convert the character entities in the text provided.
474 * </p>
475 *
476 * @param hTMLText a text to convert all the character entities in
477 * @return formatted text where all of the characters are converted to the
478 * appropriate character entities.
479 */
480 public final String format(final String hTMLText) {
481 StringBuffer returnBuffer = new StringBuffer();
482 int length = hTMLText.length();
483 int index;
484 int indexStart = hTMLText.indexOf(KEEP_START);
485 int indexEnd;
486 for (int n = 0; n < length; ++n) {
487 // if we have reached the next keep section (and there is one)
488 if ((indexStart > -1) && (indexStart == n)) {
489 // find the end of the keep section
490 if ((indexEnd = hTMLText.indexOf(KEEP_END, indexStart)) != -1) {
491 int keepEndPosition = KEEP_END.length() + 1;
492 returnBuffer.append(hTMLText.substring(indexStart
493 + keepEndPosition, indexEnd));
494 n = indexEnd + keepEndPosition;
495 indexStart = hTMLText.indexOf(KEEP_START, n);
496 } else {
497 // no end tag -> ignore
498 indexStart = -1;
499 }
500 } else {
501 int semiIndex = n;
502 char ch = hTMLText.charAt(n);
503 StringBuffer entity = null;
504 // is there a character entity at this point?
505 if (ch == '&') {
506 // look ahead for the semicolon
507 for (entity = new StringBuffer(MAXIMUM_ENTITY_LENGTH);
508 (semiIndex < length)
509 && ((semiIndex - n + 1) <= MAXIMUM_ENTITY_LENGTH);
510 ++semiIndex) {
511 char semi = hTMLText.charAt(semiIndex);
512 // add the character to the buffer
513 entity.append(semi);
514 // if we found a semi-colon, that's great. this is a
515 // real entity.
516 if (semi == ';') {
517 break;
518 }
519 // if this is not alphanumeric or hash, remove the
520 // entity buffer
521 if ((semi != '&') && (semi != '#')
522 && !Character.isLetterOrDigit(semi)) {
523 entity = null;
524 break;
525 }
526 }
527 }
528 // if we go in reverse direction, look for character entities
529 if (reverse) {
530 // if there was an entity, try to convert it
531 if (entity == null) {
532 returnBuffer.append(ch);
533 } else if (entity.toString().equalsIgnoreCase("nbsp")) {
534 // this is a special case - it only translates one way
535 returnBuffer.append(' ');
536 n = semiIndex;
537 } else {
538 String compare = entity.toString();
539 for (int arrayIndex = 0;
540 arrayIndex < entitiesArray.length;
541 ++arrayIndex) {
542 if (entitiesArray[arrayIndex].equals(compare)) {
543 returnBuffer.append(entityMapString
544 .charAt(arrayIndex));
545 entity = null;
546 n = semiIndex;
547 break;
548 }
549 }
550 if (entity != null) {
551 returnBuffer.append(ch);
552 }
553 }
554 } else if (entity == null) {
555 // see if we should convert the character
556 if ((index = entityMapString.indexOf(ch)) == -1) {
557 returnBuffer.append(ch);
558 } else {
559 returnBuffer.append(entitiesArray[index]);
560 }
561 } else {
562 // if this is not reverse direction, and an entity was found
563 // then skip past it no matter what
564 n = semiIndex;
565 returnBuffer.append(entity.toString());
566 }
567 }
568 }
569 return returnBuffer.toString();
570 }
571 /***
572 * <p>
573 * Gets whether or not character entity conversion goes in the opposite
574 * direction. If character entities are converted to characters then this
575 * method returns <code>true</code>, otherwise <code>false</code>
576 * </p>
577 *
578 * @return <code>true</code> if character entities are converted to
579 * characters, otherwise <code>false</code>/
580 */
581 public final boolean isReverse() {
582 return reverse;
583 }
584 /***
585 * <p>
586 * Set whether or not character entity conversion goes in the opposite
587 * direction.
588 * </p>
589 *
590 * @param newReverse set to <code>true</code> if character entities should
591 * be converted to characters, otherwise <code>false</code>.
592 */
593 public final void setReverse(final boolean newReverse) {
594 reverse = newReverse;
595 }
596 }