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.impl.xs.util;
019:
020: import org.apache.xerces.util.SymbolHash;
021: import org.apache.xerces.xni.QName;
022: import org.apache.xerces.xs.*;
023:
024: /**
025: * Containts the map between qnames and XSObject's.
026: *
027: * @xerces.internal
028: *
029: * @author Sandy Gao, IBM
030: *
031: * @version $Id: XSNamedMapImpl.java 446723 2006-09-15 20:37:45Z mrglavas $
032: */
033: public class XSNamedMapImpl implements XSNamedMap {
034:
035: /**
036: * An immutable empty map.
037: */
038: public static final XSNamedMap EMPTY_MAP = new XSNamedMap() {
039: public int getLength() {
040: return 0;
041: }
042:
043: public XSObject itemByName(String namespace, String localName) {
044: return null;
045: }
046:
047: public XSObject item(int index) {
048: return null;
049: }
050: };
051:
052: // components of these namespaces are stored in this map
053: String[] fNamespaces;
054: // number of namespaces
055: int fNSNum;
056: // each entry contains components in one namespace
057: SymbolHash[] fMaps;
058: // store all components from all namespace.
059: // used when this map is accessed as a list.
060: XSObject[] fArray = null;
061: // store the number of componetns.
062: // used when this map is accessed as a list.
063: int fLength = -1;
064: // temprory QName object
065: QName fName = new QName();
066:
067: /**
068: * Construct an XSNamedMap implmentation for one namespace
069: *
070: * @param namespace the namespace to which the components belong
071: * @param map the map from local names to components
072: */
073: public XSNamedMapImpl(String namespace, SymbolHash map) {
074: fNamespaces = new String[] { namespace };
075: fMaps = new SymbolHash[] { map };
076: fNSNum = 1;
077: }
078:
079: /**
080: * Construct an XSNamedMap implmentation for a list of namespaces
081: *
082: * @param namespaces the namespaces to which the components belong
083: * @param maps the maps from local names to components
084: * @param num the number of namespaces
085: */
086: public XSNamedMapImpl(String[] namespaces, SymbolHash[] maps,
087: int num) {
088: fNamespaces = namespaces;
089: fMaps = maps;
090: fNSNum = num;
091: }
092:
093: /**
094: * Construct an XSNamedMap implmentation one namespace from an array
095: *
096: * @param array containing all components
097: * @param length number of components
098: */
099: public XSNamedMapImpl(XSObject[] array, int length) {
100: if (length == 0) {
101: fNSNum = 0;
102: fLength = 0;
103: return;
104: }
105: // because all components are from the same target namesapce,
106: // get the namespace from the first one.
107: fNamespaces = new String[] { array[0].getNamespace() };
108: fMaps = null;
109: fNSNum = 1;
110: // copy elements to the Vector
111: fArray = array;
112: fLength = length;
113: }
114:
115: /**
116: * The number of <code>XSObjects</code> in the <code>XSObjectList</code>. The
117: * range of valid child node indices is 0 to <code>length-1</code>
118: * inclusive.
119: */
120: public synchronized int getLength() {
121: if (fLength == -1) {
122: fLength = 0;
123: for (int i = 0; i < fNSNum; i++)
124: fLength += fMaps[i].getLength();
125: }
126: return fLength;
127: }
128:
129: /**
130: * Retrieves an <code>XSObject</code> specified by local name and namespace
131: * URI.
132: * @param namespace The namespace URI of the <code>XSObject</code> to
133: * retrieve.
134: * @param localName The local name of the <code>XSObject</code> to retrieve.
135: * @return A <code>XSObject</code> (of any type) with the specified local
136: * name and namespace URI, or <code>null</code> if they do not
137: * identify any <code>XSObject</code> in this map.
138: */
139: public XSObject itemByName(String namespace, String localName) {
140: for (int i = 0; i < fNSNum; i++) {
141: if (isEqual(namespace, fNamespaces[i])) {
142: // when this map is created from SymbolHash's
143: // get the component from SymbolHash
144: if (fMaps != null)
145: return (XSObject) fMaps[i].get(localName);
146: // Otherwise (it's created from an array)
147: // go through the array to find a matcing name
148: XSObject ret;
149: for (int j = 0; j < fLength; j++) {
150: ret = fArray[j];
151: if (ret.getName().equals(localName))
152: return ret;
153: }
154: return null;
155: }
156: }
157: return null;
158: }
159:
160: /**
161: * Returns the <code>index</code>th item in the map. The index starts at
162: * 0. If <code>index</code> is greater than or equal to the number of
163: * nodes in the list, this returns <code>null</code>.
164: * @param index The position in the map from which the item is to be
165: * retrieved.
166: * @return The <code>XSObject</code> at the <code>index</code>th position
167: * in the <code>XSNamedMap</code>, or <code>null</code> if that is
168: * not a valid index.
169: */
170: public synchronized XSObject item(int index) {
171: if (fArray == null) {
172: // calculate the total number of elements
173: getLength();
174: fArray = new XSObject[fLength];
175: int pos = 0;
176: // get components from all SymbolHash's
177: for (int i = 0; i < fNSNum; i++) {
178: pos += fMaps[i].getValues(fArray, pos);
179: }
180: }
181: if (index < 0 || index >= fLength)
182: return null;
183: return fArray[index];
184: }
185:
186: final boolean isEqual(String one, String two) {
187: return (one != null) ? one.equals(two) : (two == null);
188: }
189:
190: } // class XSNamedMapImpl
|