View Javadoc

1   //
2   // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v@@BUILD_VERSION@@ 
3   // 	See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
4   // 	Any modifications to this file will be lost upon recompilation of the source schema. 
5   // 	Generated on: 2005.06.30 um 05:21:08 CEST 
6   //
7   
8   package de.nierbeck.timeTrack.model.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 XMLSerializer-derived
28   * 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  	 * Sequence generator. Used as the last resort to generate unique prefix.
36  	 */
37  	private int iota = 1;
38  
39  	/***
40  	 * Used to maintain association between prefixes and URIs.
41  	 */
42  	private final NamespaceSupport nss = new NamespaceSupport();
43  
44  	/***
45  	 * A flag that indicates the current mode of this object.
46  	 */
47  	private boolean inCollectingMode;
48  
49  	/*** Assigns prefixes to URIs. Can be null. */
50  	private final NamespacePrefixMapper prefixMapper;
51  
52  	/***
53  	 * Used during the collecting mode to sort out the namespace URIs we need
54  	 * for this element.
55  	 * 
56  	 * A map from prefixes to namespace URIs.
57  	 */
58  	private final Map decls = new HashMap();
59  
60  	private final Map reverseDecls = new HashMap();
61  
62  	public NamespaceContextImpl(NamespacePrefixMapper _prefixMapper) {
63  		this.prefixMapper = _prefixMapper;
64  		// declare the default namespace binding
65  		// which are effective because of the way XML1.0 is made
66  		nss.declarePrefix("", "");
67  		nss.declarePrefix("xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
68  		// this one is taken care of by the NamespaceSupport class by default.
69  		// nss.declarePrefix( "xml", XMLConstants.XML_NS_URI );
70  	}
71  
72  	public final NamespacePrefixMapper getNamespacePrefixMapper() {
73  		return prefixMapper;
74  	}
75  
76  	//
77  	//
78  	// public methods of MarshallingContext
79  	//
80  	//
81  	/***
82  	 * @param requirePrefix
83  	 *            true if this is called for attribute name. false otherwise.
84  	 */
85  	public String declareNamespace(String namespaceUri, String preferedPrefix,
86  			boolean requirePrefix) {
87  		if (!inCollectingMode) {
88  			if (!requirePrefix && nss.getURI("").equals(namespaceUri))
89  				return ""; // can use the default prefix. use it whenever we
90  			// can
91  
92  			// find a valid prefix for this namespace URI
93  			// ASSERTION: the result is always non-null,
94  			// since we require all the namespace URIs to be declared while
95  			// this object is in collection mode.
96  			if (requirePrefix)
97  				return nss.getPrefix2(namespaceUri);
98  			else
99  				return nss.getPrefix(namespaceUri);
100 		} else {
101 			if (requirePrefix && namespaceUri.length() == 0)
102 				return "";
103 
104 			// collect this new namespace URI
105 			String prefix = (String) reverseDecls.get(namespaceUri);
106 			if (prefix != null) {
107 				if (!requirePrefix || prefix.length() != 0) {
108 					// this namespace URI is already taken care of,
109 					// and it satisfies the "requirePrefix" requirement.
110 					return prefix;
111 				} else {
112 					// the prefix was already allocated but it's "",
113 					// and we specifically need non-empty prefix.
114 
115 					// erase the current binding
116 					decls.remove(prefix);
117 					reverseDecls.remove(namespaceUri);
118 				}
119 			}
120 
121 			if (namespaceUri.length() == 0) {
122 				// the empty namespace URI needs to be bound to the default
123 				// prefix.
124 				prefix = "";
125 			} else {
126 				// see if this namespace URI is already in-scope
127 				prefix = nss.getPrefix(namespaceUri);
128 				if (prefix == null)
129 					prefix = (String) reverseDecls.get(namespaceUri);
130 
131 				if (prefix == null) {
132 					// if not, try to allocate a new one.
133 
134 					// use prefixMapper if specified. If so, just let the
135 					// prefixMapper decide if it wants to use the suggested
136 					// prefix.
137 					// otherwise our best bet is the suggested prefix.
138 					if (prefixMapper != null)
139 						prefix = prefixMapper.getPreferredPrefix(namespaceUri,
140 								preferedPrefix, requirePrefix);
141 					else
142 						prefix = preferedPrefix;
143 
144 					if (prefix == null)
145 						// if the user don't care, generate one
146 						prefix = "ns" + (iota++);
147 				}
148 			}
149 
150 			// ASSERT: prefix!=null
151 
152 			if (requirePrefix && prefix.length() == 0)
153 				// we can't map it to the default prefix. generate one.
154 				prefix = "ns" + (iota++);
155 
156 			while (true) {
157 				String existingUri = (String) decls.get(prefix);
158 
159 				if (existingUri == null) {
160 					// this prefix is unoccupied. use it
161 					decls.put(prefix, namespaceUri);
162 					reverseDecls.put(namespaceUri, prefix);
163 					return prefix;
164 				}
165 
166 				if (existingUri.length() == 0) {
167 					// we have to remap the new namespace URI to a different
168 					// prefix because the current association of ""->"" cannot
169 					// be changed
170 					;
171 				} else {
172 					// the new one takes precedence. this is necessary
173 					// because we might first assign "uri1"->"" and then
174 					// later find that ""->"" needs to be added.
175 
176 					// so change the existing one
177 					decls.put(prefix, namespaceUri);
178 					reverseDecls.put(namespaceUri, prefix);
179 
180 					namespaceUri = existingUri;
181 				}
182 
183 				// we need to find a new prefix for URI "namespaceUri"
184 				// generate a machine-made prefix
185 				prefix = "ns" + (iota++);
186 
187 				// go back to the loop and reassign
188 			}
189 		}
190 	}
191 
192 	public String getPrefix(String namespaceUri) {
193 		// even through the method name is "getPrefix", we
194 		// use this method to declare prefixes if necessary.
195 
196 		// the only time a prefix is required is when we print
197 		// attribute names, and in those cases we will call
198 		// declareNamespace method directly. So it's safe to
199 		// assume that we don't require a prefix in this case.
200 		return declareNamespace(namespaceUri, null, false);
201 	}
202 
203 	/***
204 	 * Obtains the namespace URI currently associated to the given prefix. If no
205 	 * namespace URI is associated, return null.
206 	 */
207 	public String getNamespaceURI(String prefix) {
208 		String uri = (String) decls.get(prefix);
209 		if (uri != null)
210 			return uri;
211 
212 		return nss.getURI(prefix);
213 	}
214 
215 	public Iterator getPrefixes(String namespaceUri) {
216 		// not particularly efficient implementation.
217 		Set s = new HashSet();
218 
219 		String prefix = (String) reverseDecls.get(namespaceUri);
220 		if (prefix != null)
221 			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 last
245 	 * startElement method invocation and finalizes them.
246 	 * 
247 	 * This method must be called after all the necessary namespace URIs for
248 	 * this element is reported through the declareNamespace method or the
249 	 * getPrefix method.
250 	 */
251 	public void endNamespaceDecls() {
252 		if (!decls.isEmpty()) {
253 			// most of the times decls is empty, so take advantage of it.
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))) // avoid redundant
259 					// decls.
260 					nss.declarePrefix(prefix, uri);
261 			}
262 			decls.clear();
263 			reverseDecls.clear();
264 		}
265 		inCollectingMode = false;
266 	}
267 
268 	/***
269 	 * Ends the current element context and gets back to the parent context.
270 	 * 
271 	 * This method should be called at the end of the endElement method of
272 	 * derived classes.
273 	 */
274 	public void endElement() {
275 		nss.popContext();
276 	}
277 
278 	/*** Iterates all newly declared namespace prefixes for this element. */
279 	public void iterateDeclaredPrefixes(PrefixCallback callback)
280 			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 }