KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > CharacterMapExpander


1 package net.sf.saxon.event;
2 import net.sf.saxon.om.XMLChar;
3 import net.sf.saxon.om.FastStringBuffer;
4 import net.sf.saxon.trans.XPathException;
5
6 import java.util.HashMap JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9
10 /**
11 * CharacterMapExpander: This ProxyReceiver expands characters occurring in a character map,
12  * as specified by the XSLT 2.0 xsl:character-map declaration
13 *
14 * @author Michael Kay
15 */

16
17
18 public class CharacterMapExpander extends ProxyReceiver {
19
20     private HashMap JavaDoc charMap;
21     private int min = Integer.MAX_VALUE; // the lowest mapped character
22
private int max = 0; // the highest mapped character
23
private boolean useNullMarkers = true;
24
25     /**
26      * Set the character maps to be used by this CharacterMapExpander.
27      * They are merged into a single character map if there is more than one.
28      */

29
30     public void setCharacterMaps(List JavaDoc maps) {
31             // merge the character maps, allowing definitions in a later map
32
// to overwrite definitions in an earlier map. (Note, we don't really
33
// need to do this if there is only one map, but we want to scan the keys
34
// anyway to extract the mimimum and maximum mapped characters.)
35

36         charMap = new HashMap JavaDoc(64);
37         for (int i = 0; i < maps.size(); i++) {
38             HashMap JavaDoc hashMap = (HashMap JavaDoc)maps.get(i);
39             Iterator JavaDoc keys = hashMap.keySet().iterator();
40             while (keys.hasNext()) {
41                 Integer JavaDoc next = (Integer JavaDoc)keys.next();
42                 int n = next.intValue();
43                 if (n < min) {
44                     min = n;
45                 }
46                 if (n > max) {
47                     max = n;
48                 }
49                 charMap.put(next, hashMap.get(next));
50             }
51         }
52         if (min > 0xD800) {
53             // if all the mapped characters are above the BMP, we need to check
54
// surrogates
55
min = 0xD800;
56         }
57     }
58
59     /**
60      * Indicate whether the result of character mapping should be marked using NUL
61      * characters to prevent subsequent XML or HTML character escaping
62      */

63
64     public void setUseNullMarkers(boolean use) {
65         useNullMarkers = use;
66     }
67
68     /**
69      * Output an attribute
70      */

71
72     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties)
73             throws XPathException {
74         if ((properties & ReceiverOptions.DISABLE_CHARACTER_MAPS) == 0) {
75             CharSequence JavaDoc mapped = map(value, useNullMarkers);
76             if (mapped == value) {
77                 // no mapping was done
78
super.attribute(nameCode, typeCode, value, locationId, properties);
79             } else {
80                 super.attribute(nameCode, typeCode, mapped,
81                         locationId, properties | ReceiverOptions.USE_NULL_MARKERS);
82             }
83         } else {
84             super.attribute(nameCode, typeCode, value, locationId, properties);
85         }
86     }
87
88     /**
89     * Output character data
90     */

91
92     public void characters(CharSequence JavaDoc chars, int locationId, int properties) throws XPathException {
93
94         if ((properties & ReceiverOptions.DISABLE_ESCAPING) == 0) {
95             super.characters(map(chars, useNullMarkers), locationId,
96                     (properties | ReceiverOptions.USE_NULL_MARKERS) & ~ReceiverOptions.NO_SPECIAL_CHARS);
97         } else {
98             // if the user requests disable-output-escaping, this overrides the character
99
// mapping
100
super.characters(chars, locationId, properties);
101         }
102
103     }
104
105     /**
106      * Perform the character mappping
107      * @param in the input string to be mapped
108      * @param insertNulls true if null (0) characters are to be inserted before
109      * and after replacement characters. This is done in attribute values to signal
110      * that output escaping of these characters is disabled.
111      */

112
113     private CharSequence JavaDoc map(CharSequence JavaDoc in, boolean insertNulls) {
114
115         // First scan the string to see if there are any possible mapped
116
// characters; if not, don't bother creating the new buffer
117

118         boolean move = false;
119         for (int i=0; i<in.length();) {
120             char c = in.charAt(i++);
121             if (c >= min && c <= max) {
122                 move = true;
123                 break;
124             }
125         }
126         if (!move) {
127             return in;
128         }
129
130         FastStringBuffer buffer = new FastStringBuffer(in.length()*2);
131         int i = 0;
132         while(i < in.length()) {
133             char c = in.charAt(i++);
134             if (c >= min && c <= max) {
135                 if (XMLChar.isHighSurrogate(c)) {
136                     // assume the string is properly formed
137
char d = in.charAt(i++);
138                     int s = XMLChar.supplemental(c, d);
139                     String JavaDoc rep = (String JavaDoc)charMap.get(new Integer JavaDoc(s));
140                     if (rep == null) {
141                         buffer.append(c);
142                         buffer.append(d);
143                     } else {
144                         if (insertNulls) {
145                             buffer.append((char)0);
146                             buffer.append(rep);
147                             buffer.append((char)0);
148                         } else {
149                             buffer.append(rep);
150                         }
151                     }
152                 } else {
153                     String JavaDoc rep = (String JavaDoc)charMap.get(new Integer JavaDoc(c));
154                     if (rep == null) {
155                         buffer.append(c);
156                     } else {
157                         if (insertNulls) {
158                             buffer.append((char)0);
159                             buffer.append(rep);
160                             buffer.append((char)0);
161                         } else {
162                             buffer.append(rep);
163                         }
164                     }
165                 }
166             } else {
167                 buffer.append(c);
168             }
169         }
170         return buffer;
171     }
172
173
174 };
175
176 //
177
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
178
// you may not use this file except in compliance with the License. You may obtain a copy of the
179
// License at http://www.mozilla.org/MPL/
180
//
181
// Software distributed under the License is distributed on an "AS IS" basis,
182
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
183
// See the License for the specific language governing rights and limitations under the License.
184
//
185
// The Original Code is: all this file.
186
//
187
// The Initial Developer of the Original Code is Michael H. Kay
188
//
189
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
190
//
191
// Contributor(s): none.
192
//
193

194
Popular Tags