001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.xinclude;
019:
020: import java.util.Enumeration;
021:
022: import org.apache.xerces.util.NamespaceSupport;
023: import org.apache.xerces.util.XMLSymbols;
024: import org.apache.xerces.xni.NamespaceContext;
025:
026: /**
027: * This implementation of NamespaceContext has the ability to maintain multiple
028: * scopes of namespace/prefix bindings. This is useful in situations when it is
029: * not always appropriate for elements to inherit the namespace bindings of their
030: * ancestors (such as included elements in XInclude).
031: *
032: * When searching for a URI to match a prefix, or a prefix to match a URI, it is
033: * searched for in the current context, then the ancestors of the current context,
034: * up to the beginning of the current scope. Other scopes are not searched.
035: *
036: * @author Peter McCracken, IBM
037: *
038: * @version $Id: MultipleScopeNamespaceSupport.java 447243 2006-09-18 05:15:27Z mrglavas $
039: */
040: public class MultipleScopeNamespaceSupport extends NamespaceSupport {
041:
042: protected int[] fScope = new int[8];
043: protected int fCurrentScope;
044:
045: /**
046: *
047: */
048: public MultipleScopeNamespaceSupport() {
049: super ();
050: fCurrentScope = 0;
051: fScope[0] = 0;
052: }
053:
054: /**
055: * @param context
056: */
057: public MultipleScopeNamespaceSupport(NamespaceContext context) {
058: super (context);
059: fCurrentScope = 0;
060: fScope[0] = 0;
061: }
062:
063: /* (non-Javadoc)
064: * @see org.apache.xerces.xni.NamespaceContext#getAllPrefixes()
065: */
066: public Enumeration getAllPrefixes() {
067: int count = 0;
068: if (fPrefixes.length < (fNamespace.length / 2)) {
069: // resize prefix array
070: String[] prefixes = new String[fNamespaceSize];
071: fPrefixes = prefixes;
072: }
073: String prefix = null;
074: boolean unique = true;
075: for (int i = fContext[fScope[fCurrentScope]]; i <= (fNamespaceSize - 2); i += 2) {
076: prefix = fNamespace[i];
077: for (int k = 0; k < count; k++) {
078: if (fPrefixes[k] == prefix) {
079: unique = false;
080: break;
081: }
082: }
083: if (unique) {
084: fPrefixes[count++] = prefix;
085: }
086: unique = true;
087: }
088: return new Prefixes(fPrefixes, count);
089: }
090:
091: public int getScopeForContext(int context) {
092: int scope = fCurrentScope;
093: while (context < fScope[scope]) {
094: scope--;
095: }
096: return scope;
097: }
098:
099: /* (non-Javadoc)
100: * @see org.apache.xerces.xni.NamespaceContext#getPrefix(java.lang.String)
101: */
102: public String getPrefix(String uri) {
103: return getPrefix(uri, fNamespaceSize,
104: fContext[fScope[fCurrentScope]]);
105: }
106:
107: /* (non-Javadoc)
108: * @see org.apache.xerces.xni.NamespaceContext#getURI(java.lang.String)
109: */
110: public String getURI(String prefix) {
111: return getURI(prefix, fNamespaceSize,
112: fContext[fScope[fCurrentScope]]);
113: }
114:
115: public String getPrefix(String uri, int context) {
116: return getPrefix(uri, fContext[context + 1],
117: fContext[fScope[getScopeForContext(context)]]);
118: }
119:
120: public String getURI(String prefix, int context) {
121: return getURI(prefix, fContext[context + 1],
122: fContext[fScope[getScopeForContext(context)]]);
123: }
124:
125: public String getPrefix(String uri, int start, int end) {
126: // this saves us from having a copy of each of these in fNamespace for each scope
127: if (uri == NamespaceContext.XML_URI) {
128: return XMLSymbols.PREFIX_XML;
129: }
130: if (uri == NamespaceContext.XMLNS_URI) {
131: return XMLSymbols.PREFIX_XMLNS;
132: }
133:
134: // find uri in current context
135: for (int i = start; i > end; i -= 2) {
136: if (fNamespace[i - 1] == uri) {
137: if (getURI(fNamespace[i - 2]) == uri)
138: return fNamespace[i - 2];
139: }
140: }
141:
142: // uri not found
143: return null;
144: }
145:
146: public String getURI(String prefix, int start, int end) {
147: // this saves us from having a copy of each of these in fNamespace for each scope
148: if (prefix == XMLSymbols.PREFIX_XML) {
149: return NamespaceContext.XML_URI;
150: }
151: if (prefix == XMLSymbols.PREFIX_XMLNS) {
152: return NamespaceContext.XMLNS_URI;
153: }
154:
155: // find prefix in current context
156: for (int i = start; i > end; i -= 2) {
157: if (fNamespace[i - 2] == prefix) {
158: return fNamespace[i - 1];
159: }
160: }
161:
162: // prefix not found
163: return null;
164: }
165:
166: /**
167: * Only resets the current scope -- all namespaces defined in lower scopes
168: * remain valid after a call to reset.
169: */
170: public void reset() {
171: fCurrentContext = fScope[fCurrentScope];
172: fNamespaceSize = fContext[fCurrentContext];
173: }
174:
175: /**
176: * Begins a new scope. None of the previous namespace bindings will be used,
177: * until the new scope is popped with popScope()
178: */
179: public void pushScope() {
180: if (fCurrentScope + 1 == fScope.length) {
181: int[] contextarray = new int[fScope.length * 2];
182: System.arraycopy(fScope, 0, contextarray, 0, fScope.length);
183: fScope = contextarray;
184: }
185: pushContext();
186: fScope[++fCurrentScope] = fCurrentContext;
187: }
188:
189: /**
190: * Pops the current scope. The namespace bindings from the new current scope
191: * are then used for searching for namespaces and prefixes.
192: */
193: public void popScope() {
194: fCurrentContext = fScope[fCurrentScope--];
195: popContext();
196: }
197: }
|