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.xml.stream;
031:
032: import com.caucho.util.L10N;
033:
034: import com.caucho.vfs.WriteStream;
035:
036: import javax.xml.XMLConstants;
037: import javax.xml.namespace.NamespaceContext;
038: import javax.xml.namespace.QName;
039: import javax.xml.stream.XMLStreamException;
040: import java.io.IOException;
041: import java.util.ArrayList;
042: import java.util.HashMap;
043: import java.util.Iterator;
044: import java.util.Map;
045:
046: /**
047: * Maintains a stack of namespace contexts
048: */
049: public abstract class NamespaceContextImpl implements NamespaceContext {
050: public static final L10N L = new L10N(NamespaceContextImpl.class);
051:
052: // The stack of element bindings
053: protected final ArrayList<ElementBinding> _stack = new ArrayList<ElementBinding>();
054:
055: protected int _version = 0;
056:
057: NamespaceContextImpl() {
058: _stack.add(null);
059: }
060:
061: public int getDepth() {
062: return _stack.size() - 1;
063: }
064:
065: /**
066: * Creates a new subcontext and enters it
067: */
068: public void push() {
069: _stack.add(null);
070: }
071:
072: /**
073: * deletes the current context and enters its parent
074: */
075: public void pop() throws XMLStreamException {
076: if (_stack.size() == 0)
077: throw new XMLStreamException(L
078: .l("Multiple root elements in document"));
079:
080: ElementBinding eltBinding = _stack.remove(_stack.size() - 1);
081:
082: if (eltBinding != null) {
083: ArrayList<Decl> oldBinding = eltBinding.getOldBindingList();
084:
085: for (int i = 0; oldBinding != null && i < oldBinding.size(); i++) {
086: Decl decl = oldBinding.get(i);
087: NamespaceBinding binding = decl.getBinding();
088:
089: if (decl.getOldUri() == null)
090: remove(binding.getPrefix(), binding.getUri());
091: else {
092: _version++;
093:
094: binding.setUri(decl.getOldUri());
095: binding.setVersion(_version);
096: }
097: }
098:
099: eltBinding.clear();
100: }
101: }
102:
103: public void setElementName(QName name) {
104: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
105:
106: if (eltBinding == null) {
107: eltBinding = new ElementBinding();
108:
109: _stack.set(_stack.size() - 1, eltBinding);
110: }
111:
112: eltBinding.setName(name);
113: }
114:
115: public QName getElementName() {
116: ElementBinding eltBinding = _stack.get(_stack.size() - 1);
117:
118: if (eltBinding != null)
119: return eltBinding.getName();
120: else
121: return null;
122: }
123:
124: /**
125: * declares a new namespace prefix in the current context
126: */
127: public abstract void declare(String prefix, String uri);
128:
129: protected abstract void remove(String prefix, String uri);
130:
131: static class ElementBinding {
132: private QName _name;
133: private ArrayList<Decl> _declList;
134:
135: public void setName(QName name) {
136: _name = name;
137: }
138:
139: public void clear() {
140: _declList = null;
141: }
142:
143: public QName getName() {
144: return _name;
145: }
146:
147: public void addOldBinding(NamespaceBinding binding,
148: String prefix, String oldUri, String newUri) {
149: if (_declList == null)
150: _declList = new ArrayList<Decl>();
151:
152: _declList.add(new Decl(binding, prefix, oldUri, newUri));
153: }
154:
155: public ArrayList<Decl> getOldBindingList() {
156: return _declList;
157: }
158: }
159:
160: static class Decl {
161: private final NamespaceBinding _binding;
162: private final String _prefix;
163: private final String _oldUri;
164: private final String _newUri;
165:
166: Decl(NamespaceBinding binding, String prefix, String oldUri,
167: String newUri) {
168: _binding = binding;
169: _prefix = prefix;
170: _oldUri = oldUri;
171: _newUri = newUri;
172: }
173:
174: NamespaceBinding getBinding() {
175: return _binding;
176: }
177:
178: String getPrefix() {
179: return _prefix;
180: }
181:
182: String getOldUri() {
183: return _oldUri;
184: }
185:
186: String getNewUri() {
187: return _newUri;
188: }
189:
190: public String toString() {
191: return "Decl[binding=" + _binding + ",prefix=" + _prefix
192: + ",oldUri=" + _oldUri + ",newUri=" + _newUri + "]";
193: }
194: }
195:
196: static class PrefixIterator {
197: private ElementBinding _eltBinding;
198: private int _index = 0;
199:
200: PrefixIterator(NamespaceContextImpl context,
201: ElementBinding eltBinding) {
202: _eltBinding = eltBinding;
203: }
204:
205: public void remove() {
206: throw new RuntimeException("not supported");
207: }
208:
209: public boolean hasNext() {
210: if (_eltBinding == null)
211: return false;
212:
213: return _index < _eltBinding.getOldBindingList().size();
214: }
215:
216: public Object next() {
217: if (_eltBinding == null)
218: return null;
219:
220: ArrayList<Decl> oldBindingList = _eltBinding
221: .getOldBindingList();
222:
223: if (_index < oldBindingList.size())
224: return oldBindingList.get(_index++).getPrefix();
225:
226: return null;
227: }
228: }
229: }
|