1
2
3
4
5
6
7
8 package net.sf.jour.config.impl.runtime;
9
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.Map;
15 import java.util.Set;
16
17 import javax.xml.XMLConstants;
18
19 import org.xml.sax.SAXException;
20
21 import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
22 import com.sun.xml.bind.marshaller.NamespaceSupport;
23
24 /***
25 * Implementation of the NamespaceContext2.
26 *
27 * This class also provides several utility methods for
28 * XMLSerializer-derived classes.
29 *
30 * The startElement method and the endElement method need to be called
31 * appropriately when used. See javadoc for those methods for details.
32 */
33 public class NamespaceContextImpl implements NamespaceContext2
34 {
35 /***
36 * Sequence generator. Used as the last resort to generate
37 * unique prefix.
38 */
39 private int iota = 1;
40
41 /***
42 * Used to maintain association between prefixes and URIs.
43 */
44 private final NamespaceSupport nss = new NamespaceSupport();
45
46 /***
47 * A flag that indicates the current mode of this object.
48 */
49 private boolean inCollectingMode;
50
51 /*** Assigns prefixes to URIs. Can be null. */
52 private final NamespacePrefixMapper prefixMapper;
53
54 /***
55 * Used during the collecting mode to sort out the namespace
56 * URIs we need for this element.
57 *
58 * A map from prefixes to namespace URIs.
59 */
60 private final Map decls = new HashMap();
61
62 private final Map reverseDecls = new HashMap();
63
64
65 public NamespaceContextImpl(NamespacePrefixMapper _prefixMapper) {
66 this.prefixMapper = _prefixMapper;
67
68
69 nss.declarePrefix("","");
70 nss.declarePrefix( "xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI );
71
72
73 }
74
75 public final NamespacePrefixMapper getNamespacePrefixMapper() {
76 return prefixMapper;
77 }
78
79
80
81
82
83
84 /***
85 * @param requirePrefix
86 * true if this is called for attribute name. false otherwise.
87 */
88 public String declareNamespace( String namespaceUri, String preferedPrefix, boolean requirePrefix ) {
89 if( !inCollectingMode ) {
90 if( !requirePrefix && nss.getURI("").equals(namespaceUri) )
91 return "";
92
93
94
95
96
97 if (requirePrefix)
98 return nss.getPrefix2(namespaceUri);
99 else
100 return nss.getPrefix(namespaceUri);
101 } else {
102 if( requirePrefix && namespaceUri.length()==0 )
103 return "";
104
105
106 String prefix = (String)reverseDecls.get(namespaceUri);
107 if( prefix!=null ) {
108 if( !requirePrefix || prefix.length()!=0 ) {
109
110
111 return prefix;
112 } else {
113
114
115
116
117 decls.remove(prefix);
118 reverseDecls.remove(namespaceUri);
119 }
120 }
121
122
123 if( namespaceUri.length()==0 ) {
124
125 prefix = "";
126 } else {
127
128 prefix = nss.getPrefix(namespaceUri);
129 if( prefix==null )
130 prefix = (String)reverseDecls.get(namespaceUri);
131
132 if( prefix==null ) {
133
134
135
136
137
138 if( prefixMapper!=null )
139 prefix = prefixMapper.getPreferredPrefix(
140 namespaceUri,preferedPrefix,requirePrefix);
141 else
142 prefix = preferedPrefix;
143
144 if( prefix==null )
145
146 prefix = "ns"+(iota++);
147 }
148 }
149
150
151
152 if( requirePrefix && prefix.length()==0 )
153
154 prefix = "ns"+(iota++);
155
156
157 while(true) {
158 String existingUri = (String)decls.get(prefix);
159
160 if( existingUri==null ) {
161
162 decls.put( prefix, namespaceUri );
163 reverseDecls.put( namespaceUri, prefix );
164 return prefix;
165 }
166
167 if( existingUri.length()==0 ) {
168
169
170
171 ;
172 } else {
173
174
175
176
177
178 decls.put( prefix, namespaceUri );
179 reverseDecls.put( namespaceUri, prefix );
180
181 namespaceUri = existingUri;
182 }
183
184
185
186 prefix = "ns"+(iota++);
187
188
189 }
190 }
191 }
192
193
194 public String getPrefix( String namespaceUri ) {
195
196
197
198
199
200
201
202 return declareNamespace(namespaceUri,null,false);
203 }
204
205 /***
206 * Obtains the namespace URI currently associated to the given prefix.
207 * If no namespace URI is associated, return null.
208 */
209 public String getNamespaceURI( String prefix ) {
210 String uri = (String)decls.get(prefix);
211 if(uri!=null) return uri;
212
213 return nss.getURI(prefix);
214 }
215
216 public Iterator getPrefixes( String namespaceUri ) {
217
218 Set s = new HashSet();
219
220 String prefix = (String)reverseDecls.get(namespaceUri);
221 if(prefix!=null) s.add(prefix);
222
223 if( nss.getURI("").equals(namespaceUri) )
224 s.add("");
225
226 for( Enumeration e=nss.getPrefixes(namespaceUri); e.hasMoreElements(); )
227 s.add(e.nextElement());
228
229 return s.iterator();
230 }
231
232 /***
233 * Sets the current bindings aside and starts a new element context.
234 *
235 * This method should be called at the beginning of the startElement method
236 * of the Serializer implementation.
237 */
238 public void startElement() {
239 nss.pushContext();
240 inCollectingMode = true;
241 }
242
243 /***
244 * Reconciles the namespace URI/prefix mapping requests since the
245 * last startElement method invocation and finalizes them.
246 *
247 * This method must be called after all the necessary namespace URIs
248 * for this element is reported through the declareNamespace method
249 * or the getPrefix method.
250 */
251 public void endNamespaceDecls() {
252 if(!decls.isEmpty()) {
253
254 for( Iterator itr=decls.entrySet().iterator(); itr.hasNext(); ) {
255 Map.Entry e = (Map.Entry)itr.next();
256 String prefix = (String)e.getKey();
257 String uri = (String)e.getValue();
258 if(!uri.equals(nss.getURI(prefix)))
259 nss.declarePrefix( prefix, uri );
260 }
261 decls.clear();
262 reverseDecls.clear();
263 }
264 inCollectingMode = false;
265 }
266
267 /***
268 * Ends the current element context and gets back to the parent context.
269 *
270 * This method should be called at the end of the endElement method
271 * of derived classes.
272 */
273 public void endElement() {
274 nss.popContext();
275 }
276
277
278
279 /*** Iterates all newly declared namespace prefixes for this element. */
280 public void iterateDeclaredPrefixes( PrefixCallback callback ) throws SAXException {
281 for( Enumeration e=nss.getDeclaredPrefixes(); e.hasMoreElements(); ) {
282 String p = (String)e.nextElement();
283 String uri = nss.getURI(p);
284
285 callback.onPrefixMapping( p, uri );
286 }
287 }
288
289
290 }