View Javadoc

1   //
2   // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v1.0.3-b18-fcs 
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: 2004.12.16 at 07:09:42 EST 
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          // declare the default namespace binding
68          // which are effective because of the way XML1.0 is made
69          nss.declarePrefix("","");
70          nss.declarePrefix( "xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI );
71  // this one is taken care of by the NamespaceSupport class by default.
72  //        nss.declarePrefix( "xml",   XMLConstants.XML_NS_URI );
73      }
74      
75      public final NamespacePrefixMapper getNamespacePrefixMapper() {
76          return prefixMapper;
77      }
78      
79  //
80  //
81  // public methods of MarshallingContext
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 "";  // can use the default prefix. use it whenever we can
92              
93              // find a valid prefix for this namespace URI
94              // ASSERTION: the result is always non-null,
95              // since we require all the namespace URIs to be declared while
96              // this object is in collection mode.
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             // collect this new namespace URI
106             String prefix = (String)reverseDecls.get(namespaceUri);
107             if( prefix!=null ) {
108                 if( !requirePrefix || prefix.length()!=0 ) {
109                     // this namespace URI is already taken care of,
110                     // and it satisfies the "requirePrefix" requirement.
111                     return prefix;
112                 } else {
113                     // the prefix was already allocated but it's "",
114                     // and we specifically need non-empty prefix.
115                     
116                     // erase the current binding
117                     decls.remove(prefix);
118                     reverseDecls.remove(namespaceUri);
119                 }
120             }
121             
122             
123             if( namespaceUri.length()==0 ) {
124                 // the empty namespace URI needs to be bound to the default prefix.
125                 prefix = "";
126             } else {
127                 // see if this namespace URI is already in-scope
128                 prefix = nss.getPrefix(namespaceUri);
129                 if( prefix==null )
130                     prefix = (String)reverseDecls.get(namespaceUri);
131                 
132                 if( prefix==null ) {
133                     // if not, try to allocate a new one.
134                     
135                     // use prefixMapper if specified. If so, just let the 
136                     // prefixMapper decide if it wants to use the suggested prefix.
137                     // otherwise our best bet is the suggested prefix.
138                     if( prefixMapper!=null )
139                         prefix = prefixMapper.getPreferredPrefix(
140                             namespaceUri,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             
157             while(true) {
158                 String existingUri = (String)decls.get(prefix);
159                 
160                 if( existingUri==null ) {
161                     // this prefix is unoccupied. use it
162                     decls.put( prefix, namespaceUri );
163                     reverseDecls.put( namespaceUri, prefix );
164                     return prefix;
165                 }
166                 
167                 if( existingUri.length()==0 ) {
168                     // we have to remap the new namespace URI to a different
169                     // prefix because the current association of ""->"" cannot
170                     // be changed
171                     ;
172                 } else {
173                     // the new one takes precedence. this is necessary
174                     // because we might first assign "uri1"->"" and then
175                     // later find that ""->"" needs to be added.
176                     
177                     // so change the existing one
178                     decls.put( prefix, namespaceUri );
179                     reverseDecls.put( namespaceUri, prefix );
180                     
181                     namespaceUri = existingUri;
182                 }
183                 
184                 // we need to find a new prefix for URI "namespaceUri"
185                 // generate a machine-made prefix
186                 prefix = "ns"+(iota++);
187                 
188                 // go back to the loop and reassign
189             }
190         }
191     }
192     
193 
194     public String getPrefix( String namespaceUri ) {
195         // even through the method name is "getPrefix", we 
196         // use this method to declare prefixes if necessary.
197         
198         // the only time a prefix is required is when we print
199         // attribute names, and in those cases we will call
200         // declareNamespace method directly. So it's safe to
201         // assume that we don't require a prefix in this case.
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         // not particularly efficient implementation.
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             // 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 decls.
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 }