001//
002// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v1.0.6-01/24/2006 06:15 PM(kohsuke)-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: 2012.10.03 at 04:27:47 AM CEST 
006//
007
008package org.jdtaus.mojo.resource.model.impl.runtime;
009
010import java.util.Enumeration;
011import java.util.HashMap;
012import java.util.HashSet;
013import java.util.Iterator;
014import java.util.Map;
015import java.util.Set;
016
017import javax.xml.XMLConstants;
018
019import org.xml.sax.SAXException;
020
021import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
022import com.sun.xml.bind.marshaller.NamespaceSupport;
023
024/**
025 * Implementation of the NamespaceContext2.
026 * 
027 * This class also provides several utility methods for
028 * XMLSerializer-derived classes.
029 * 
030 * The startElement method and the endElement method need to be called
031 * appropriately when used. See javadoc for those methods for details.
032 */
033public class NamespaceContextImpl implements NamespaceContext2
034{
035    /**
036     * Sequence generator. Used as the last resort to generate
037     * unique prefix.
038     */
039    private int iota = 1;
040    
041    /**
042     * Used to maintain association between prefixes and URIs.
043     */
044    private final NamespaceSupport nss = new NamespaceSupport();
045    
046    /**
047     * A flag that indicates the current mode of this object.
048     */
049    private boolean inCollectingMode;
050    
051    /** Assigns prefixes to URIs. Can be null. */
052    private final NamespacePrefixMapper prefixMapper;
053    
054    /**
055     * Used during the collecting mode to sort out the namespace
056     * URIs we need for this element.
057     * 
058     * A map from prefixes to namespace URIs.
059     */
060    private final Map decls = new HashMap();
061    
062    private final Map reverseDecls = new HashMap();
063    
064    
065    public NamespaceContextImpl(NamespacePrefixMapper _prefixMapper) {
066        this.prefixMapper = _prefixMapper;
067        // declare the default namespace binding
068        // which are effective because of the way XML1.0 is made
069        nss.declarePrefix("","");
070        nss.declarePrefix( "xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI );
071// this one is taken care of by the NamespaceSupport class by default.
072//        nss.declarePrefix( "xml",   XMLConstants.XML_NS_URI );
073    }
074    
075    public final NamespacePrefixMapper getNamespacePrefixMapper() {
076        return prefixMapper;
077    }
078    
079//
080//
081// public methods of MarshallingContext
082//
083//
084    /**
085     * @param requirePrefix
086     *      true if this is called for attribute name. false otherwise.
087     */
088    public String declareNamespace( String namespaceUri, String preferedPrefix, boolean requirePrefix ) {
089        if( !inCollectingMode ) {
090            if( !requirePrefix && nss.getURI("").equals(namespaceUri) )
091                return "";  // can use the default prefix. use it whenever we can
092            
093            // find a valid prefix for this namespace URI
094            // ASSERTION: the result is always non-null,
095            // since we require all the namespace URIs to be declared while
096            // this object is in collection mode.
097            if (requirePrefix)
098                return nss.getPrefix2(namespaceUri);
099            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}