001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.xml.stream;
031:
032: import com.caucho.vfs.WriteStream;
033:
034: import static javax.xml.XMLConstants.*;
035: import javax.xml.namespace.NamespaceContext;
036: import javax.xml.namespace.QName;
037: import java.io.IOException;
038: import java.util.ArrayList;
039: import java.util.HashMap;
040: import java.util.Iterator;
041: import java.util.Map;
042: import java.util.NoSuchElementException;
043:
044: /**
045: * Maintains a stack of namespace contexts
046: */
047: public class NamespaceReaderContext extends NamespaceContextImpl {
048: // The current prefix -> namespace bindings
049: private final HashMap<String, NamespaceBinding> _bindings = new HashMap<String, NamespaceBinding>();
050:
051: private NamespaceBinding _nullEltBinding = new NamespaceBinding(
052: null, null, 0);
053: private NamespaceBinding _nullAttrBinding = new NamespaceBinding(
054: null, null, 0);
055:
056: protected void remove(String prefix, String uri) {
057: _bindings.remove(prefix);
058: }
059:
060: /**
061: * declares a new namespace prefix in the current context
062: */
063: public void declare(String prefix, String uri) {
064: NamespaceBinding binding = getElementNamespace(prefix);
065:
066: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
067:
068: if (eltBinding == null) {
069: eltBinding = new ElementBinding();
070:
071: _stack.set(_stack.size() - 1, eltBinding);
072: }
073:
074: eltBinding
075: .addOldBinding(binding, prefix, binding.getUri(), uri);
076:
077: _version++;
078: binding.setUri(uri);
079: binding.setVersion(_version);
080: }
081:
082: /**
083: * looks up the prefix, returns the uri it corresponds to
084: */
085: public String getUri(String prefix) {
086: NamespaceBinding binding = _bindings.get(prefix);
087:
088: if (binding != null)
089: return binding.getUri();
090: else
091: return null;
092: }
093:
094: // --> javax.xml.namespace.NamespaceContext
095:
096: public String getNamespaceURI(String prefix) {
097: if (prefix == null)
098: throw new IllegalArgumentException("Prefix may not be null");
099:
100: NamespaceBinding binding = _bindings.get(prefix);
101:
102: if (binding != null)
103: return binding.getUri();
104:
105: String uri = null;
106:
107: if (XML_NS_PREFIX.equals(prefix))
108: uri = XML_NS_URI;
109: else if (XMLNS_ATTRIBUTE.equals(prefix))
110: uri = XMLNS_ATTRIBUTE_NS_URI;
111:
112: return uri;
113: }
114:
115: // inefficient, but the TCK uses it and virtually nobody else should
116: public String getPrefix(String uri) {
117: if (uri == null)
118: throw new IllegalArgumentException("URI may not be null");
119: else if ("".equals(uri))
120: throw new IllegalArgumentException("URI may not be empty");
121: else if (XML_NS_URI.equals(uri))
122: return XML_NS_PREFIX;
123: else if (XMLNS_ATTRIBUTE_NS_URI.equals(uri))
124: return XMLNS_ATTRIBUTE;
125:
126: Iterator<NamespaceBinding> iterator = _bindings.values()
127: .iterator();
128:
129: while (iterator.hasNext()) {
130: NamespaceBinding binding = iterator.next();
131:
132: if (uri.equals(binding.getUri()))
133: return binding.getPrefix();
134: }
135:
136: return null;
137: }
138:
139: public Iterator getPrefixes(String uri) {
140: return new PrefixIterator(uri);
141: }
142:
143: // <-- javax.xml.namespace.NamespaceContext
144:
145: // --> used by StaxIntern
146: public int getNumDecls() {
147: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
148:
149: if (eltBinding != null) {
150: ArrayList<Decl> oldBindingList = eltBinding
151: .getOldBindingList();
152:
153: if (oldBindingList != null)
154: return oldBindingList.size();
155: else
156: return 0;
157: } else
158: return 0;
159: }
160:
161: public String getUri(int i) {
162: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
163:
164: if (eltBinding != null) {
165: return eltBinding.getOldBindingList().get(i).getNewUri();
166: } else
167: return null;
168: }
169:
170: public String getPrefix(int i) {
171: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
172:
173: if (eltBinding != null) {
174: return eltBinding.getOldBindingList().get(i).getPrefix();
175: }
176:
177: return null;
178: }
179:
180: // <-- used by StaxIntern
181:
182: NamespaceBinding getElementNamespace(String prefix) {
183: NamespaceBinding binding;
184:
185: // default namespace
186: if (prefix == null)
187: binding = _nullEltBinding;
188: else
189: binding = _bindings.get(prefix);
190:
191: if (binding != null)
192: return binding;
193: else {
194: binding = new NamespaceBinding(prefix, null, _version);
195:
196: _bindings.put(prefix, binding);
197:
198: return binding;
199: }
200: }
201:
202: NamespaceBinding getAttributeNamespace(String prefix) {
203: NamespaceBinding binding;
204:
205: // default namespace
206: if (prefix == null || DEFAULT_NS_PREFIX.equals(prefix))
207: binding = _nullAttrBinding;
208: else
209: binding = _bindings.get(prefix);
210:
211: if (binding != null)
212: return binding;
213: else {
214: binding = new NamespaceBinding(prefix, null, _version);
215:
216: _bindings.put(prefix, binding);
217:
218: return binding;
219: }
220: }
221:
222: private class PrefixIterator implements Iterator {
223: private String _uri;
224: private String _prefix;
225: private Iterator<NamespaceBinding> _iterator;
226:
227: public PrefixIterator(String uri) {
228: _uri = uri;
229: _iterator = _bindings.values().iterator();
230: advance();
231: }
232:
233: public boolean hasNext() {
234: return _prefix != null;
235: }
236:
237: public Object next() {
238: if (!hasNext())
239: throw new NoSuchElementException();
240:
241: String prefix = _prefix;
242:
243: advance();
244:
245: return prefix;
246: }
247:
248: public void remove() {
249: throw new UnsupportedOperationException();
250: }
251:
252: private void advance() {
253: _prefix = null;
254:
255: while (_iterator.hasNext()) {
256: NamespaceBinding binding = _iterator.next();
257:
258: if (_uri.equals(binding.getUri())) {
259: _prefix = binding.getPrefix();
260: break;
261: }
262: }
263: }
264: }
265:
266: public void print() {
267: for (NamespaceBinding binding : _bindings.values())
268: System.out.println(binding.toString());
269: }
270: }
|