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 Adam Megacz
028: */
029:
030: package com.caucho.xml2;
031:
032: import com.caucho.vfs.WriteStream;
033:
034: import 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:
043: /**
044: * Maintains a stack of namespace contexts
045: */
046: public class NamespaceContextImpl {
047: // The current namespace bindings
048: private final HashMap<String, NamespaceBinding> _bindings = new HashMap<String, NamespaceBinding>();
049:
050: // The stack of element bindings
051: private ElementBinding[] _stack = new ElementBinding[32];
052: private int _stackTop;
053:
054: private NamespaceBinding _nullEltBinding;
055: private NamespaceBinding _nullAttrBinding;
056:
057: private int _uniqueId = 0;
058: private int _version = 0;
059:
060: NamespaceContextImpl() {
061: _nullEltBinding = new NamespaceBinding(null, null, 0);
062: _nullAttrBinding = new NamespaceBinding(null, null, 0);
063:
064: _stackTop = 1;
065: }
066:
067: /**
068: * Creates a new subcontext and enters it
069: */
070: public void push(SaxIntern.Entry entry) {
071: ElementBinding elt = _stack[_stackTop];
072:
073: if (elt == null) {
074: elt = new ElementBinding();
075: _stack[_stackTop] = elt;
076: }
077:
078: _stackTop++;
079:
080: elt.setName(entry);
081: }
082:
083: /**
084: * deletes the current context and enters its parent
085: */
086: public void pop(SaxIntern.Entry entry) {
087: ElementBinding eltBinding = _stack[--_stackTop];
088:
089: if (eltBinding != null) {
090: ArrayList<Decl> oldBinding = eltBinding.getOldBindingList();
091:
092: for (int i = 0; oldBinding != null && i < oldBinding.size(); i++) {
093: Decl decl = oldBinding.get(i);
094: NamespaceBinding binding = decl.getBinding();
095:
096: _version++;
097:
098: binding.setUri(decl.getOldUri());
099: binding.setVersion(_version);
100: }
101:
102: eltBinding.clear();
103: }
104: }
105:
106: public int getDepth() {
107: return _stackTop - 1;
108: }
109:
110: /**
111: * declares a new namespace prefix in the current context
112: */
113: public void declare(String prefix, String uri) {
114: NamespaceBinding binding = getElementNamespace(prefix);
115:
116: ElementBinding eltBinding = _stack[_stackTop - 1];
117:
118: if (eltBinding == null) {
119: eltBinding = new ElementBinding();
120:
121: _stack[_stackTop - 1] = eltBinding;
122: }
123:
124: eltBinding
125: .addOldBinding(binding, prefix, binding.getUri(), uri);
126:
127: _version++;
128: binding.setUri(uri);
129: binding.setVersion(_version);
130: }
131:
132: /**
133: * declares a new namespace prefix in the current context; the
134: * auto-allocated prefix is returned
135: */
136: public String declare(String uri) {
137: String prefix = "ns" + _uniqueId++;
138:
139: declare(prefix, uri);
140:
141: return prefix;
142: }
143:
144: /**
145: * looks up the prefix, returns the uri it corresponds to
146: */
147: public String getUri(String prefix) {
148: NamespaceBinding binding = _bindings.get(prefix);
149:
150: if (binding != null)
151: return binding.getUri();
152: else
153: return null;
154: }
155:
156: public String getNamespaceURI(String prefix) {
157: NamespaceBinding binding = _bindings.get(prefix);
158:
159: if (binding != null)
160: return binding.getUri();
161:
162: String uri = null;
163:
164: if (XMLConstants.XML_NS_PREFIX.equals(prefix))
165: uri = XMLConstants.XML_NS_URI;
166: else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
167: uri = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
168:
169: return uri;
170: }
171:
172: public Iterator getPrefixes(String uri) {
173: return null;
174: }
175:
176: public String getUri(int i) {
177: ElementBinding eltBinding = _stack[_stackTop - 1];
178:
179: if (eltBinding != null) {
180: return eltBinding.getOldBindingList().get(i).getNewUri();
181: } else
182: return null;
183: }
184:
185: public String getPrefix(int i) {
186: ElementBinding eltBinding = _stack[_stackTop - 1];
187:
188: if (eltBinding != null) {
189: return eltBinding.getOldBindingList().get(i).getPrefix();
190: }
191:
192: return null;
193: }
194:
195: public int getNumDecls() {
196: ElementBinding eltBinding = _stack[_stackTop - 1];
197:
198: if (eltBinding != null)
199: return eltBinding.getOldBindingList().size();
200: else
201: return 0;
202: }
203:
204: NamespaceBinding getElementNamespace(String prefix) {
205: NamespaceBinding binding;
206:
207: if (prefix == null)
208: binding = _nullEltBinding;
209: else
210: binding = _bindings.get(prefix);
211:
212: if (binding != null)
213: return binding;
214: else {
215: binding = new NamespaceBinding(prefix, null, _version);
216:
217: _bindings.put(prefix, binding);
218:
219: return binding;
220: }
221: }
222:
223: NamespaceBinding getAttributeNamespace(String prefix) {
224: NamespaceBinding binding;
225:
226: if (prefix == null)
227: binding = _nullAttrBinding;
228: else
229: binding = _bindings.get(prefix);
230:
231: if (binding != null)
232: return binding;
233: else {
234: binding = new NamespaceBinding(prefix, null, _version);
235:
236: _bindings.put(prefix, binding);
237:
238: return binding;
239: }
240: }
241:
242: static class ElementBinding {
243: private SaxIntern.Entry _name;
244: private ArrayList<Decl> _declList;
245:
246: public void setName(SaxIntern.Entry name) {
247: _name = name;
248: }
249:
250: public SaxIntern.Entry getName() {
251: return _name;
252: }
253:
254: public void addOldBinding(NamespaceBinding binding,
255: String prefix, String oldUri, String newUri) {
256: if (_declList == null)
257: _declList = new ArrayList<Decl>();
258:
259: _declList.add(new Decl(binding, prefix, oldUri, newUri));
260: }
261:
262: public ArrayList<Decl> getOldBindingList() {
263: return _declList;
264: }
265:
266: public void clear() {
267: _declList = null;
268: }
269: }
270:
271: static class Decl {
272: private final NamespaceBinding _binding;
273: private final String _prefix;
274: private final String _oldUri;
275: private final String _newUri;
276:
277: Decl(NamespaceBinding binding, String prefix, String oldUri,
278: String newUri) {
279: _binding = binding;
280: _prefix = prefix;
281: _oldUri = oldUri;
282: _newUri = newUri;
283: }
284:
285: NamespaceBinding getBinding() {
286: return _binding;
287: }
288:
289: String getPrefix() {
290: return _prefix;
291: }
292:
293: String getOldUri() {
294: return _oldUri;
295: }
296:
297: String getNewUri() {
298: return _newUri;
299: }
300: }
301: }
|