001    //
002    // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v1.0.1-05/30/2003 05:06 AM(java_re)-fcs 
003    // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
004    // Any modifications to this file will be lost upon recompilation of the source schema. 
005    // Generated on: 2004.10.11 at 12:13:34 EDT 
006    //
007    
008    /*
009     * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
010     * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
011     */
012    
013    package astronomy.data.spectra.impl.runtime;
014    
015    import java.util.Enumeration;
016    import java.util.HashMap;
017    import java.util.HashSet;
018    import java.util.Iterator;
019    import java.util.Map;
020    import java.util.Set;
021    
022    import javax.xml.XMLConstants;
023    
024    import org.xml.sax.SAXException;
025    
026    import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
027    import com.sun.xml.bind.marshaller.NamespaceSupport;
028    
029    /**
030     * Implementation of the NamespaceContext2.
031     * 
032     * This class also provides several utility methods for
033     * XMLSerializer-derived classes.
034     * 
035     * The startElement method and the endElement method need to be called
036     * appropriately when used. See javadoc for those methods for details.
037     */
038    public class NamespaceContextImpl implements NamespaceContext2
039    {
040        /**
041         * Sequence generator. Used as the last resort to generate
042         * unique prefix.
043         */
044        private int iota = 1;
045        
046        /**
047         * Used to maintain association between prefixes and URIs.
048         */
049        private final NamespaceSupport nss = new NamespaceSupport();
050        
051        /**
052         * A flag that indicates the current mode of this object.
053         */
054        private boolean inCollectingMode;
055        
056        /** Assigns prefixes to URIs. Can be null. */
057        private final NamespacePrefixMapper prefixMapper;
058        
059        /**
060         * Used during the collecting mode to sort out the namespace
061         * URIs we need for this element.
062         * 
063         * A map from prefixes to namespace URIs.
064         */
065        private final Map decls = new HashMap();
066        
067        private final Map reverseDecls = new HashMap();
068        
069        
070        public NamespaceContextImpl(NamespacePrefixMapper _prefixMapper) {
071            this.prefixMapper = _prefixMapper;
072            // declare the default namespace binding
073            // which are effective because of the way XML1.0 is made
074            nss.declarePrefix("","");
075            nss.declarePrefix( "xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI );
076    // this one is taken care of by the NamespaceSupport class by default.
077    //        nss.declarePrefix( "xml",   XMLConstants.XML_NS_URI );
078        }
079    
080    //
081    //
082    // public methods of MarshallingContext
083    //
084    //
085        /**
086         * @param requirePrefix
087         *      true if this is called for attribute name. false otherwise.
088         */
089        public String declareNamespace( String namespaceUri, String preferedPrefix, boolean requirePrefix ) {
090            if( !inCollectingMode ) {
091                if( !requirePrefix && nss.getURI("").equals(namespaceUri) )
092                    return "";  // can use the default prefix. use it whenever we can
093                
094                // find a valid prefix for this namespace URI
095                // ASSERTION: the result is always non-null,
096                // since we require all the namespace URIs to be declared while
097                // this object is in collection mode.
098                return nss.getPrefix(namespaceUri);
099            } else {
100                if( requirePrefix && namespaceUri.length()==0 )
101                    return "";
102                
103                // collect this new namespace URI
104                String prefix = (String)reverseDecls.get(namespaceUri);
105                if( prefix!=null ) {
106                    if( !requirePrefix || prefix.length()!=0 ) {
107                        // this namespace URI is already taken care of,
108                        // and it satisfies the "requirePrefix" requirement.
109                        return prefix;
110                    } else {
111                        // the prefix was already allocated but it's "",
112                        // and we specifically need non-empty prefix.
113                        
114                        // erase the current binding
115                        decls.remove(prefix);
116                        reverseDecls.remove(namespaceUri);
117                    }
118                }
119                
120                
121                if( namespaceUri.length()==0 ) {
122                    // the empty namespace URI needs to be bound to the default prefix.
123                    prefix = "";
124                } else {
125                    // see if this namespace URI is already in-scope
126                    prefix = nss.getPrefix(namespaceUri);
127                    if( prefix==null )
128                        prefix = (String)reverseDecls.get(namespaceUri);
129                    
130                    if( prefix==null ) {
131                        // if not, try to allocate a new one.
132                        
133                        // use prefixMapper if specified. If so, just let the 
134                        // prefixMapper decide if it wants to use the suggested prefix.
135                        // otherwise our best bet is the suggested prefix.
136                        if( prefixMapper!=null )
137                            prefix = prefixMapper.getPreferredPrefix(
138                                namespaceUri,preferedPrefix,requirePrefix);
139                        else
140                           prefix = preferedPrefix;
141    
142                        if( prefix==null )
143                            // if the user don't care, generate one
144                            prefix = "ns"+(iota++);
145                    }
146                }
147    
148                // ASSERT: prefix!=null
149                
150                if( requirePrefix && prefix.length()==0 )
151                    // we can't map it to the default prefix. generate one.
152                    prefix = "ns"+(iota++);
153                
154                
155                while(true) {
156                    String existingUri = (String)decls.get(prefix);
157                    
158                    if( existingUri==null ) {
159                        // this prefix is unoccupied. use it
160                        decls.put( prefix, namespaceUri );
161                        reverseDecls.put( namespaceUri, prefix );
162                        return prefix;
163                    }
164                    
165                    if( existingUri.length()==0 ) {
166                        // we have to remap the new namespace URI to a different
167                        // prefix because the current association of ""->"" cannot
168                        // be changed
169                        ;
170                    } else {
171                        // the new one takes precedence. this is necessary
172                        // because we might first assign "uri1"->"" and then
173                        // later find that ""->"" needs to be added.
174                        
175                        // so change the existing one
176                        decls.put( prefix, namespaceUri );
177                        reverseDecls.put( namespaceUri, prefix );
178                        
179                        namespaceUri = existingUri;
180                    }
181                    
182                    // we need to find a new prefix for URI "namespaceUri"
183                    // generate a machine-made prefix
184                    prefix = "ns"+(iota++);
185                    
186                    // go back to the loop and reassign
187                }
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.
205         * If no namespace URI is associated, return null.
206         */
207        public String getNamespaceURI( String prefix ) {
208            String uri = (String)decls.get(prefix);
209            if(uri!=null)       return uri;
210            
211            return nss.getURI(prefix);
212        }
213        
214        public Iterator getPrefixes( String namespaceUri ) {
215            // not particularly efficient implementation.
216            Set s = new HashSet();
217            
218            String prefix = (String)reverseDecls.get(namespaceUri);
219            if(prefix!=null)    s.add(prefix);
220            
221            if( nss.getURI("").equals(namespaceUri) )
222                s.add("");
223            
224            for( Enumeration e=nss.getPrefixes(namespaceUri); e.hasMoreElements(); )
225                s.add(e.nextElement());
226            
227            return s.iterator();
228        }
229    
230        /**
231         * Sets the current bindings aside and starts a new element context.
232         * 
233         * This method should be called at the beginning of the startElement method
234         * of the Serializer implementation.
235         */
236        public void startElement() {
237            nss.pushContext();
238            inCollectingMode = true;
239        }
240        
241        /**
242         * Reconciles the namespace URI/prefix mapping requests since the
243         * last startElement method invocation and finalizes them.
244         * 
245         * This method must be called after all the necessary namespace URIs 
246         * for this element is reported through the declareNamespace method
247         * or the getPrefix method.
248         */
249        public void endNamespaceDecls() {
250            for( Iterator itr=decls.entrySet().iterator(); itr.hasNext(); ) {
251                Map.Entry e = (Map.Entry)itr.next();
252                String prefix = (String)e.getKey();
253                String uri = (String)e.getValue();
254                if(!uri.equals(nss.getURI(prefix))) // avoid redundant decls.
255                    nss.declarePrefix( prefix, uri );
256            }
257            decls.clear();
258            reverseDecls.clear();
259            inCollectingMode = false;
260        }
261        
262        /**
263         * Ends the current element context and gets back to the parent context.
264         * 
265         * This method should be called at the end of the endElement method
266         * of derived classes.
267         */
268        public void endElement() {
269            nss.popContext();
270        }
271    
272        
273        
274        /** Iterates all newly declared namespace prefixes for this element. */
275        public void iterateDeclaredPrefixes( PrefixCallback callback ) throws SAXException {
276            for( Enumeration e=nss.getDeclaredPrefixes(); e.hasMoreElements(); ) {
277                String p = (String)e.nextElement();
278                String uri = nss.getURI(p);
279                
280                callback.onPrefixMapping( p, uri );
281            }
282        }
283        
284        
285    }