001: /*
002: * Fast Infoset ver. 0.1 software ("Software")
003: *
004: * Copyright, 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * Software is licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License. You may
008: * obtain a copy of the License at:
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations.
016: *
017: * Sun supports and benefits from the global community of open source
018: * developers, and thanks the community for its important contributions and
019: * open standards-based technology, which Sun has adopted into many of its
020: * products.
021: *
022: * Please note that portions of Software may be provided with notices and
023: * open source licenses from such communities and third parties that govern the
024: * use of those portions, and any licenses granted hereunder do not alter any
025: * rights and obligations you may have under such open source licenses,
026: * however, the disclaimer of warranty and limitation of liability provisions
027: * in this License will apply to all Software in this distribution.
028: *
029: * You acknowledge that the Software is not designed, licensed or intended
030: * for use in the design, construction, operation or maintenance of any nuclear
031: * facility.
032: *
033: * Apache License
034: * Version 2.0, January 2004
035: * http://www.apache.org/licenses/
036: *
037: */
038:
039: package com.sun.xml.fastinfoset.util;
040:
041: import com.sun.xml.fastinfoset.EncodingConstants;
042: import com.sun.xml.fastinfoset.CommonResourceBundle;
043: import java.util.Iterator;
044: import java.util.NoSuchElementException;
045: import org.jvnet.fastinfoset.FastInfosetException;
046:
047: public class PrefixArray extends ValueArray {
048: public static final int PREFIX_MAP_SIZE = 64;
049:
050: private int _initialCapacity;
051:
052: public String[] _array;
053:
054: private PrefixArray _readOnlyArray;
055:
056: private static class PrefixEntry {
057: private PrefixEntry next;
058: private int prefixId;
059: }
060:
061: private PrefixEntry[] _prefixMap = new PrefixEntry[PREFIX_MAP_SIZE];
062:
063: private PrefixEntry _prefixPool;
064:
065: private static class NamespaceEntry {
066: private NamespaceEntry next;
067: private int declarationId;
068: private int namespaceIndex;
069:
070: private String prefix;
071: private String namespaceName;
072: private int prefixEntryIndex;
073: }
074:
075: private NamespaceEntry _namespacePool;
076:
077: private NamespaceEntry[] _inScopeNamespaces;
078:
079: public int[] _currentInScope;
080:
081: public int _declarationId;
082:
083: public PrefixArray(int initialCapacity, int maximumCapacity) {
084: _initialCapacity = initialCapacity;
085: _maximumCapacity = maximumCapacity;
086:
087: _array = new String[initialCapacity];
088: // Sizes of _inScopeNamespaces and _currentInScope need to be two
089: // greater than _array because 0 represents the empty string and
090: // 1 represents the xml prefix
091: _inScopeNamespaces = new NamespaceEntry[initialCapacity + 2];
092: _currentInScope = new int[initialCapacity + 2];
093:
094: increaseNamespacePool(initialCapacity);
095: increasePrefixPool(initialCapacity);
096:
097: initializeEntries();
098: }
099:
100: public PrefixArray() {
101: this (DEFAULT_CAPACITY, MAXIMUM_CAPACITY);
102: }
103:
104: private final void initializeEntries() {
105: _inScopeNamespaces[0] = _namespacePool;
106: _namespacePool = _namespacePool.next;
107: _inScopeNamespaces[0].next = null;
108: _inScopeNamespaces[0].prefix = "";
109: _inScopeNamespaces[0].namespaceName = "";
110: _inScopeNamespaces[0].namespaceIndex = _currentInScope[0] = 0;
111:
112: int index = KeyIntMap.indexFor(KeyIntMap
113: .hashHash(_inScopeNamespaces[0].prefix.hashCode()),
114: _prefixMap.length);
115: _prefixMap[index] = _prefixPool;
116: _prefixPool = _prefixPool.next;
117: _prefixMap[index].next = null;
118: _prefixMap[index].prefixId = 0;
119:
120: _inScopeNamespaces[1] = _namespacePool;
121: _namespacePool = _namespacePool.next;
122: _inScopeNamespaces[1].next = null;
123: _inScopeNamespaces[1].prefix = EncodingConstants.XML_NAMESPACE_PREFIX;
124: _inScopeNamespaces[1].namespaceName = EncodingConstants.XML_NAMESPACE_NAME;
125: _inScopeNamespaces[1].namespaceIndex = _currentInScope[1] = 1;
126:
127: index = KeyIntMap.indexFor(KeyIntMap
128: .hashHash(_inScopeNamespaces[1].prefix.hashCode()),
129: _prefixMap.length);
130: if (_prefixMap[index] == null) {
131: _prefixMap[index] = _prefixPool;
132: _prefixPool = _prefixPool.next;
133: _prefixMap[index].next = null;
134: } else {
135: final PrefixEntry e = _prefixMap[index];
136: _prefixMap[index] = _prefixPool;
137: _prefixPool = _prefixPool.next;
138: _prefixMap[index].next = e;
139: }
140: _prefixMap[index].prefixId = 1;
141: }
142:
143: private final void increaseNamespacePool(int capacity) {
144: if (_namespacePool == null) {
145: _namespacePool = new NamespaceEntry();
146: }
147:
148: for (int i = 0; i < capacity; i++) {
149: NamespaceEntry ne = new NamespaceEntry();
150: ne.next = _namespacePool;
151: _namespacePool = ne;
152: }
153: }
154:
155: private final void increasePrefixPool(int capacity) {
156: if (_prefixPool == null) {
157: _prefixPool = new PrefixEntry();
158: }
159:
160: for (int i = 0; i < capacity; i++) {
161: PrefixEntry pe = new PrefixEntry();
162: pe.next = _prefixPool;
163: _prefixPool = pe;
164: }
165: }
166:
167: public int countNamespacePool() {
168: int i = 0;
169: NamespaceEntry e = _namespacePool;
170: while (e != null) {
171: i++;
172: e = e.next;
173: }
174: return i;
175: }
176:
177: public int countPrefixPool() {
178: int i = 0;
179: PrefixEntry e = _prefixPool;
180: while (e != null) {
181: i++;
182: e = e.next;
183: }
184: return i;
185: }
186:
187: public final void clear() {
188: for (int i = _readOnlyArraySize; i < _size; i++) {
189: _array[i] = null;
190: }
191: _size = _readOnlyArraySize;
192: }
193:
194: public final void clearCompletely() {
195: _prefixPool = null;
196: _namespacePool = null;
197:
198: for (int i = 0; i < _size + 2; i++) {
199: _currentInScope[i] = 0;
200: _inScopeNamespaces[i] = null;
201: }
202:
203: for (int i = 0; i < _prefixMap.length; i++) {
204: _prefixMap[i] = null;
205: }
206:
207: increaseNamespacePool(_initialCapacity);
208: increasePrefixPool(_initialCapacity);
209:
210: initializeEntries();
211:
212: _declarationId = 0;
213:
214: clear();
215: }
216:
217: public final String[] getArray() {
218: return _array;
219: }
220:
221: public final void setReadOnlyArray(ValueArray readOnlyArray,
222: boolean clear) {
223: if (!(readOnlyArray instanceof PrefixArray)) {
224: throw new IllegalArgumentException(CommonResourceBundle
225: .getInstance().getString("message.illegalClass",
226: new Object[] { readOnlyArray }));
227: }
228:
229: setReadOnlyArray((PrefixArray) readOnlyArray, clear);
230: }
231:
232: public final void setReadOnlyArray(PrefixArray readOnlyArray,
233: boolean clear) {
234: if (readOnlyArray != null) {
235: _readOnlyArray = readOnlyArray;
236: _readOnlyArraySize = readOnlyArray.getSize();
237:
238: clearCompletely();
239:
240: // Resize according to size of read only arrays
241: _inScopeNamespaces = new NamespaceEntry[_readOnlyArraySize
242: + _inScopeNamespaces.length];
243: _currentInScope = new int[_readOnlyArraySize
244: + _currentInScope.length];
245: // Intialize first two entries
246: initializeEntries();
247:
248: if (clear) {
249: clear();
250: }
251:
252: _array = getCompleteArray();
253: _size = _readOnlyArraySize;
254: }
255: }
256:
257: public final String[] getCompleteArray() {
258: if (_readOnlyArray == null) {
259: return _array;
260: } else {
261: final String[] ra = _readOnlyArray.getCompleteArray();
262: final String[] a = new String[_readOnlyArraySize
263: + _array.length];
264: System.arraycopy(ra, 0, a, 0, _readOnlyArraySize);
265: return a;
266: }
267: }
268:
269: public final String get(int i) {
270: return _array[i];
271: }
272:
273: public final int add(String s) {
274: if (_size == _array.length) {
275: resize();
276: }
277:
278: _array[_size++] = s;
279: return _size;
280: }
281:
282: protected final void resize() {
283: if (_size == _maximumCapacity) {
284: throw new ValueArrayResourceException(CommonResourceBundle
285: .getInstance()
286: .getString("message.arrayMaxCapacity"));
287: }
288:
289: int newSize = _size * 3 / 2 + 1;
290: if (newSize > _maximumCapacity) {
291: newSize = _maximumCapacity;
292: }
293:
294: final String[] newArray = new String[newSize];
295: System.arraycopy(_array, 0, newArray, 0, _size);
296: _array = newArray;
297:
298: newSize += 2;
299: final NamespaceEntry[] newInScopeNamespaces = new NamespaceEntry[newSize];
300: System.arraycopy(_inScopeNamespaces, 0, newInScopeNamespaces,
301: 0, _inScopeNamespaces.length);
302: _inScopeNamespaces = newInScopeNamespaces;
303:
304: final int[] newCurrentInScope = new int[newSize];
305: System.arraycopy(_currentInScope, 0, newCurrentInScope, 0,
306: _currentInScope.length);
307: _currentInScope = newCurrentInScope;
308: }
309:
310: public final void clearDeclarationIds() {
311: for (int i = 0; i < _size; i++) {
312: final NamespaceEntry e = _inScopeNamespaces[i];
313: if (e != null) {
314: e.declarationId = 0;
315: }
316: }
317:
318: _declarationId = 1;
319: }
320:
321: public final void pushScope(int prefixIndex, int namespaceIndex)
322: throws FastInfosetException {
323: if (_namespacePool == null) {
324: increaseNamespacePool(16);
325: }
326:
327: final NamespaceEntry e = _namespacePool;
328: _namespacePool = e.next;
329:
330: final NamespaceEntry current = _inScopeNamespaces[++prefixIndex];
331: if (current == null) {
332: e.declarationId = _declarationId;
333: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
334: e.next = null;
335:
336: _inScopeNamespaces[prefixIndex] = e;
337: } else if (current.declarationId < _declarationId) {
338: e.declarationId = _declarationId;
339: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
340: e.next = current;
341:
342: current.declarationId = 0;
343: _inScopeNamespaces[prefixIndex] = e;
344: } else {
345: throw new FastInfosetException(CommonResourceBundle
346: .getInstance().getString(
347: "message.duplicateNamespaceAttribute"));
348: }
349: }
350:
351: public final void pushScopeWithPrefixEntry(String prefix,
352: String namespaceName, int prefixIndex, int namespaceIndex)
353: throws FastInfosetException {
354: if (_namespacePool == null) {
355: increaseNamespacePool(16);
356: }
357: if (_prefixPool == null) {
358: increasePrefixPool(16);
359: }
360:
361: final NamespaceEntry e = _namespacePool;
362: _namespacePool = e.next;
363:
364: final NamespaceEntry current = _inScopeNamespaces[++prefixIndex];
365: if (current == null) {
366: e.declarationId = _declarationId;
367: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
368: e.next = null;
369:
370: _inScopeNamespaces[prefixIndex] = e;
371: } else if (current.declarationId < _declarationId) {
372: e.declarationId = _declarationId;
373: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
374: e.next = current;
375:
376: current.declarationId = 0;
377: _inScopeNamespaces[prefixIndex] = e;
378: } else {
379: throw new FastInfosetException(CommonResourceBundle
380: .getInstance().getString(
381: "message.duplicateNamespaceAttribute"));
382: }
383:
384: final PrefixEntry p = _prefixPool;
385: _prefixPool = _prefixPool.next;
386: p.prefixId = prefixIndex;
387:
388: e.prefix = prefix;
389: e.namespaceName = namespaceName;
390: e.prefixEntryIndex = KeyIntMap.indexFor(KeyIntMap
391: .hashHash(prefix.hashCode()), _prefixMap.length);
392:
393: final PrefixEntry pCurrent = _prefixMap[e.prefixEntryIndex];
394: p.next = pCurrent;
395: _prefixMap[e.prefixEntryIndex] = p;
396: }
397:
398: public final void popScope(int prefixIndex) {
399: final NamespaceEntry e = _inScopeNamespaces[++prefixIndex];
400: _inScopeNamespaces[prefixIndex] = e.next;
401: _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex
402: : 0;
403:
404: e.next = _namespacePool;
405: _namespacePool = e;
406: }
407:
408: public final void popScopeWithPrefixEntry(int prefixIndex) {
409: final NamespaceEntry e = _inScopeNamespaces[++prefixIndex];
410:
411: _inScopeNamespaces[prefixIndex] = e.next;
412: _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex
413: : 0;
414:
415: e.prefix = e.namespaceName = null;
416: e.next = _namespacePool;
417: _namespacePool = e;
418:
419: PrefixEntry current = _prefixMap[e.prefixEntryIndex];
420: if (current.prefixId == prefixIndex) {
421: _prefixMap[e.prefixEntryIndex] = current.next;
422: current.next = _prefixPool;
423: _prefixPool = current;
424: } else {
425: PrefixEntry prev = current;
426: current = current.next;
427: while (current != null) {
428: if (current.prefixId == prefixIndex) {
429: prev.next = current.next;
430: current.next = _prefixPool;
431: _prefixPool = current;
432: break;
433: }
434: prev = current;
435: current = current.next;
436: }
437: }
438: }
439:
440: public final String getNamespaceFromPrefix(String prefix) {
441: final int index = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix
442: .hashCode()), _prefixMap.length);
443: PrefixEntry pe = _prefixMap[index];
444: while (pe != null) {
445: final NamespaceEntry ne = _inScopeNamespaces[pe.prefixId];
446: if (prefix == ne.prefix || prefix.equals(ne.prefix)) {
447: return ne.namespaceName;
448: }
449: pe = pe.next;
450: }
451:
452: return null;
453: }
454:
455: public final String getPrefixFromNamespace(String namespaceName) {
456: int position = 0;
457: while (++position < _size + 2) {
458: final NamespaceEntry ne = _inScopeNamespaces[position];
459: if (ne != null && namespaceName.equals(ne.namespaceName)) {
460: return ne.prefix;
461: }
462: }
463:
464: return null;
465: }
466:
467: public final Iterator getPrefixes() {
468: return new Iterator() {
469: int _position = 1;
470: NamespaceEntry _ne = _inScopeNamespaces[_position];
471:
472: public boolean hasNext() {
473: return _ne != null;
474: }
475:
476: public Object next() {
477: if (_position == _size + 2) {
478: throw new NoSuchElementException();
479: }
480:
481: final String prefix = _ne.prefix;
482: moveToNext();
483: return prefix;
484: }
485:
486: public void remove() {
487: throw new UnsupportedOperationException();
488: }
489:
490: private final void moveToNext() {
491: while (++_position < _size + 2) {
492: _ne = _inScopeNamespaces[_position];
493: if (_ne != null) {
494: return;
495: }
496: }
497: _ne = null;
498: }
499:
500: };
501: }
502:
503: public final Iterator getPrefixesFromNamespace(
504: final String namespaceName) {
505: return new Iterator() {
506: String _namespaceName = namespaceName;
507: int _position = 0;
508: NamespaceEntry _ne;
509:
510: {
511: moveToNext();
512: }
513:
514: public boolean hasNext() {
515: return _ne != null;
516: }
517:
518: public Object next() {
519: if (_position == _size + 2) {
520: throw new NoSuchElementException();
521: }
522:
523: final String prefix = _ne.prefix;
524: moveToNext();
525: return prefix;
526: }
527:
528: public void remove() {
529: throw new UnsupportedOperationException();
530: }
531:
532: private final void moveToNext() {
533: while (++_position < _size + 2) {
534: _ne = _inScopeNamespaces[_position];
535: if (_ne != null
536: && _namespaceName.equals(_ne.namespaceName)) {
537: return;
538: }
539: }
540: _ne = null;
541: }
542: };
543: }
544: }
|