View Javadoc
1   /*
2    * Copyright 2011 Jakub Narloch
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.exolab.castor.xml;
17  
18  import java.util.ArrayList;
19  import java.util.Enumeration;
20  import java.util.List;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.xml.sax.helpers.AttributeListImpl;
25  
26  /**
27   * This class is an actual namespace stack implementation, responsible for
28   * adding and removing namespace scopes, as well as resolving namespace urls and
29   * prefixes by traversing all the namespace stack.
30   * 
31   * @author <a href="mailto:jmnarloch AT gmail DOT com">Jakub Narloch</a>
32   * @since 1.3.3
33   */
34  @SuppressWarnings("deprecation")
35  public class NamespacesStack {
36  
37     private final Log logger = LogFactory.getLog(this.getClass());
38     
39     /**
40      * Represents the string used for indicating default namespace, by default
41      * empty string is used.
42      */
43     private static final String DEFAULT_NAMESPACE = "";
44  
45     /**
46      * Represents a stack of namespaces.
47      */
48     private List<Namespaces> namespaceStack = new ArrayList<Namespaces>();
49  
50     /**
51      * Adds a namespace to current scope.
52      * 
53      * @param namespacePrefix
54      *           the namespace prefix
55      * @param namespaceUri
56      *           the namespace uri
57      */
58     public void addNamespace(String namespacePrefix, String namespaceUri) {
59        Namespaces namespaces = getCurrentNamespaceScope();
60        if (namespaces != null) {
61           namespaces.addNamespace(namespacePrefix, namespaceUri);
62        }
63     }
64  
65     /**
66      * Adds the default namespace to current scope.
67      * 
68      * @param namespaceUri
69      *           the namespace uri
70      */
71     public void addDefaultNamespace(String namespaceUri) {
72        addNamespace(DEFAULT_NAMESPACE, namespaceUri);
73     }
74  
75     /**
76      * Removes the namespace from current scope using the namespace prefix
77      * 
78      * @param namespacePrefix
79      *           the prefix of the namespace to remove
80      */
81     public void removeNamespace(String namespacePrefix) {
82        getCurrentNamespaceScope().removeNamespace(namespacePrefix);
83     }
84  
85     /**
86      * Retrieves the namespace uri bound to specified prefix.
87      * 
88      * @param namespacePrefix
89      *           the namespace prefix
90      * 
91      * @return the namespace uri bound to the prefix, or null if no namespace has
92      *         been bound for the given prefix
93      */
94     public String getNamespaceURI(String namespacePrefix) {
95        String namespaceUri = null;
96        for (int ind = namespaceStack.size() - 1; ind >= 0 && namespaceUri == null; ind--) {
97           namespaceUri = namespaceStack.get(ind).getNamespaceURI(namespacePrefix);
98        }
99        return namespaceUri;
100    }
101 
102    /**
103     * Declares the namespaces using the attribute list.
104     * 
105     * @param attributeList
106     *           the list of attributes containing the namespaces
107     * @param localOnly
108     *           whether the namespaces will only registered in current namespace
109     *           context or in entire stack
110     */
111    @SuppressWarnings("deprecation")
112    public void declareAsAttributes(AttributeListImpl attributeList, boolean localOnly) {
113       getCurrentNamespaceScope().declareAsAttributes(attributeList);
114       if (!localOnly) {
115          for (int ind = namespaceStack.size() - 1; ind >= 0; ind--) {
116 
117             namespaceStack.get(ind).declareAsAttributes(attributeList);
118          }
119       }
120    }
121 
122    /**
123     * Retrieves the default namespace namespace uri.
124     * 
125     * @return the default namespace uri
126     */
127    public String getDefaultNamespaceURI() {
128       return getNamespaceURI(DEFAULT_NAMESPACE);
129    }
130 
131    /**
132     * Retrieves the namespace prefix for the given namespace uri.
133     * 
134     * @param namespaceUri
135     *           the namespace uri
136     * 
137     * @return the
138     */
139    public String getNamespacePrefix(String namespaceUri) {
140       String namespacePrefix = null;
141       for (int ind = namespaceStack.size() - 1; ind >= 0 && namespacePrefix == null; ind--) {
142          namespacePrefix = namespaceStack.get(ind).getNamespacePrefix(namespaceUri);
143       }
144       return namespacePrefix;
145    }
146 
147    /**
148     * Retrieves the non default namespace prefix for the given namespace uri.
149     * 
150     * @param namespaceUri
151     *           the namespace uri
152     * 
153     * @return the
154     */
155    public String getNonDefaultNamespacePrefix(String namespaceUri) {
156       String namespacePrefix = null;
157       for (int ind = namespaceStack.size() - 1; ind >= 0 && namespacePrefix == null; ind--) {
158          namespacePrefix = namespaceStack.get(ind).getNonDefaultNamespacePrefix(namespaceUri);
159       }
160       return namespacePrefix;
161    }
162 
163    /**
164     * Retrieves the namespace prefixes registered in current scope.
165     * 
166     * @return the enumeration of namespace prefixes
167     */
168    public Enumeration<String> getLocalNamespacePrefixes() {
169       Namespaces namespaces = getCurrentNamespaceScope();
170       return namespaces != null ? namespaces.getLocalNamespacePrefixes() : null;
171    }
172 
173    /**
174     * Adds a new namespace scope.
175     */
176    public void addNewNamespaceScope() {
177       namespaceStack.add(new Namespaces());
178    }
179 
180    /**
181     * Removes the namespace scope.
182     */
183    public void removeNamespaceScope() {
184       // removes the current namespace
185       if (namespaceStack.size() > 0) {
186          namespaceStack.remove(namespaceStack.size() - 1);
187       } else {
188          this.logger.error("Trying to remove a namespaces scope from an empty stack of Namespaces");
189       }
190    }
191 
192    /**
193     * Retrieves the current namespace scope.
194     * 
195     * @return the current namespace scope.
196     */
197    public Namespaces getCurrentNamespaceScope() {
198       if (namespaceStack.size() == 0) {
199          addNewNamespaceScope();
200       }
201       return namespaceStack.get(namespaceStack.size() - 1);
202    }
203 }