/* * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. */ package com.sun.xml.internal.fastinfoset.util; import com.sun.xml.internal.fastinfoset.EncodingConstants; import com.sun.xml.internal.fastinfoset.CommonResourceBundle; import java.util.Iterator; import java.util.NoSuchElementException; import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; public class PrefixArray extends ValueArray { public static final int PREFIX_MAP_SIZE = 64; private int _initialCapacity; public String[] _array; private PrefixArray _readOnlyArray; private static class PrefixEntry { private PrefixEntry next; private int prefixId; } private PrefixEntry[] _prefixMap = new PrefixEntry[PREFIX_MAP_SIZE]; private PrefixEntry _prefixPool; private static class NamespaceEntry { private NamespaceEntry next; private int declarationId; private int namespaceIndex; private String prefix; private String namespaceName; private int prefixEntryIndex; } private NamespaceEntry _namespacePool; private NamespaceEntry[] _inScopeNamespaces; public int[] _currentInScope; public int _declarationId; public PrefixArray(int initialCapacity, int maximumCapacity) { _initialCapacity = initialCapacity; _maximumCapacity = maximumCapacity; _array = new String[initialCapacity]; // Sizes of _inScopeNamespaces and _currentInScope need to be two // greater than _array because 0 represents the empty string and // 1 represents the xml prefix _inScopeNamespaces = new NamespaceEntry[initialCapacity + 2]; _currentInScope = new int[initialCapacity + 2]; increaseNamespacePool(initialCapacity); increasePrefixPool(initialCapacity); initializeEntries(); } public PrefixArray() { this(DEFAULT_CAPACITY, MAXIMUM_CAPACITY); } private final void initializeEntries() { _inScopeNamespaces[0] = _namespacePool; _namespacePool = _namespacePool.next; _inScopeNamespaces[0].next = null; _inScopeNamespaces[0].prefix = ""; _inScopeNamespaces[0].namespaceName = ""; _inScopeNamespaces[0].namespaceIndex = _currentInScope[0] = 0; int index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[0].prefix.hashCode()), _prefixMap.length); _prefixMap[index] = _prefixPool; _prefixPool = _prefixPool.next; _prefixMap[index].next = null; _prefixMap[index].prefixId = 0; _inScopeNamespaces[1] = _namespacePool; _namespacePool = _namespacePool.next; _inScopeNamespaces[1].next = null; _inScopeNamespaces[1].prefix = EncodingConstants.XML_NAMESPACE_PREFIX; _inScopeNamespaces[1].namespaceName = EncodingConstants.XML_NAMESPACE_NAME; _inScopeNamespaces[1].namespaceIndex = _currentInScope[1] = 1; index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[1].prefix.hashCode()), _prefixMap.length); if (_prefixMap[index] == null) { _prefixMap[index] = _prefixPool; _prefixPool = _prefixPool.next; _prefixMap[index].next = null; } else { final PrefixEntry e = _prefixMap[index]; _prefixMap[index] = _prefixPool; _prefixPool = _prefixPool.next; _prefixMap[index].next = e; } _prefixMap[index].prefixId = 1; } private final void increaseNamespacePool(int capacity) { if (_namespacePool == null) { _namespacePool = new NamespaceEntry(); } for (int i = 0; i < capacity; i++) { NamespaceEntry ne = new NamespaceEntry(); ne.next = _namespacePool; _namespacePool = ne; } } private final void increasePrefixPool(int capacity) { if (_prefixPool == null) { _prefixPool = new PrefixEntry(); } for (int i = 0; i < capacity; i++) { PrefixEntry pe = new PrefixEntry(); pe.next = _prefixPool; _prefixPool = pe; } } public int countNamespacePool() { int i = 0; NamespaceEntry e = _namespacePool; while (e != null) { i++; e = e.next; } return i; } public int countPrefixPool() { int i = 0; PrefixEntry e = _prefixPool; while (e != null) { i++; e = e.next; } return i; } public final void clear() { for (int i = _readOnlyArraySize; i < _size; i++) { _array[i] = null; } _size = _readOnlyArraySize; } public final void clearCompletely() { _prefixPool = null; _namespacePool = null; for (int i = 0; i < _size + 2; i++) { _currentInScope[i] = 0; _inScopeNamespaces[i] = null; } for (int i = 0; i < _prefixMap.length; i++) { _prefixMap[i] = null; } increaseNamespacePool(_initialCapacity); increasePrefixPool(_initialCapacity); initializeEntries(); _declarationId = 0; clear(); } public final String[] getArray() { return _array; } public final void setReadOnlyArray(ValueArray readOnlyArray, boolean clear) { if (!(readOnlyArray instanceof PrefixArray)) { throw new IllegalArgumentException(CommonResourceBundle.getInstance(). getString("message.illegalClass", new Object[]{readOnlyArray})); } setReadOnlyArray((PrefixArray)readOnlyArray, clear); } public final void setReadOnlyArray(PrefixArray readOnlyArray, boolean clear) { if (readOnlyArray != null) { _readOnlyArray = readOnlyArray; _readOnlyArraySize = readOnlyArray.getSize(); clearCompletely(); // Resize according to size of read only arrays _inScopeNamespaces = new NamespaceEntry[_readOnlyArraySize + _inScopeNamespaces.length]; _currentInScope = new int[_readOnlyArraySize + _currentInScope.length]; // Intialize first two entries initializeEntries(); if (clear) { clear(); } _array = getCompleteArray(); _size = _readOnlyArraySize; } } public final String[] getCompleteArray() { if (_readOnlyArray == null) { return _array; } else { final String[] ra = _readOnlyArray.getCompleteArray(); final String[] a = new String[_readOnlyArraySize + _array.length]; System.arraycopy(ra, 0, a, 0, _readOnlyArraySize); return a; } } public final String get(int i) { return _array[i]; } public final int add(String s) { if (_size == _array.length) { resize(); } _array[_size++] = s; return _size; } protected final void resize() { if (_size == _maximumCapacity) { throw new ValueArrayResourceException(CommonResourceBundle.getInstance().getString("message.arrayMaxCapacity")); } int newSize = _size * 3 / 2 + 1; if (newSize > _maximumCapacity) { newSize = _maximumCapacity; } final String[] newArray = new String[newSize]; System.arraycopy(_array, 0, newArray, 0, _size); _array = newArray; newSize += 2; final NamespaceEntry[] newInScopeNamespaces = new NamespaceEntry[newSize]; System.arraycopy(_inScopeNamespaces, 0, newInScopeNamespaces, 0, _inScopeNamespaces.length); _inScopeNamespaces = newInScopeNamespaces; final int[] newCurrentInScope = new int[newSize]; System.arraycopy(_currentInScope, 0, newCurrentInScope, 0, _currentInScope.length); _currentInScope = newCurrentInScope; } public final void clearDeclarationIds() { for (int i = 0; i < _size; i++) { final NamespaceEntry e = _inScopeNamespaces[i]; if (e != null) { e.declarationId = 0; } } _declarationId = 1; } public final void pushScope(int prefixIndex, int namespaceIndex) throws FastInfosetException { if (_namespacePool == null) { increaseNamespacePool(16); } final NamespaceEntry e = _namespacePool; _namespacePool = e.next; final NamespaceEntry current = _inScopeNamespaces[++prefixIndex]; if (current == null) { e.declarationId = _declarationId; e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; e.next = null; _inScopeNamespaces[prefixIndex] = e; } else if (current.declarationId < _declarationId) { e.declarationId = _declarationId; e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; e.next = current; current.declarationId = 0; _inScopeNamespaces[prefixIndex] = e; } else { throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute")); } } public final void pushScopeWithPrefixEntry(String prefix, String namespaceName, int prefixIndex, int namespaceIndex) throws FastInfosetException { if (_namespacePool == null) { increaseNamespacePool(16); } if (_prefixPool == null) { increasePrefixPool(16); } final NamespaceEntry e = _namespacePool; _namespacePool = e.next; final NamespaceEntry current = _inScopeNamespaces[++prefixIndex]; if (current == null) { e.declarationId = _declarationId; e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; e.next = null; _inScopeNamespaces[prefixIndex] = e; } else if (current.declarationId < _declarationId) { e.declarationId = _declarationId; e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; e.next = current; current.declarationId = 0; _inScopeNamespaces[prefixIndex] = e; } else { throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute")); } final PrefixEntry p = _prefixPool; _prefixPool = _prefixPool.next; p.prefixId = prefixIndex; e.prefix = prefix; e.namespaceName = namespaceName; e.prefixEntryIndex = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length); final PrefixEntry pCurrent = _prefixMap[e.prefixEntryIndex]; p.next = pCurrent; _prefixMap[e.prefixEntryIndex] = p; } public final void popScope(int prefixIndex) { final NamespaceEntry e = _inScopeNamespaces[++prefixIndex]; _inScopeNamespaces[prefixIndex] = e.next; _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0; e.next = _namespacePool; _namespacePool = e; } public final void popScopeWithPrefixEntry(int prefixIndex) { final NamespaceEntry e = _inScopeNamespaces[++prefixIndex]; _inScopeNamespaces[prefixIndex] = e.next; _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0; e.prefix = e.namespaceName = null; e.next = _namespacePool; _namespacePool = e; PrefixEntry current = _prefixMap[e.prefixEntryIndex]; if (current.prefixId == prefixIndex) { _prefixMap[e.prefixEntryIndex] = current.next; current.next = _prefixPool; _prefixPool = current; } else { PrefixEntry prev = current; current = current.next; while (current != null) { if (current.prefixId == prefixIndex) { prev.next = current.next; current.next = _prefixPool; _prefixPool = current; break; } prev = current; current = current.next; } } } public final String getNamespaceFromPrefix(String prefix) { final int index = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length); PrefixEntry pe = _prefixMap[index]; while (pe != null) { final NamespaceEntry ne = _inScopeNamespaces[pe.prefixId]; if (prefix == ne.prefix || prefix.equals(ne.prefix)) { return ne.namespaceName; } pe = pe.next; } return null; } public final String getPrefixFromNamespace(String namespaceName) { int position = 0; while (++position < _size + 2) { final NamespaceEntry ne = _inScopeNamespaces[position]; if (ne != null && namespaceName.equals(ne.namespaceName)) { return ne.prefix; } } return null; } public final Iterator getPrefixes() { return new Iterator() { int _position = 1; NamespaceEntry _ne = _inScopeNamespaces[_position]; public boolean hasNext() { return _ne != null; } public Object next() { if (_position == _size + 2) { throw new NoSuchElementException(); } final String prefix = _ne.prefix; moveToNext(); return prefix; } public void remove() { throw new UnsupportedOperationException(); } private final void moveToNext() { while (++_position < _size + 2) { _ne = _inScopeNamespaces[_position]; if (_ne != null) { return; } } _ne = null; } }; } public final Iterator getPrefixesFromNamespace(final String namespaceName) { return new Iterator() { String _namespaceName = namespaceName; int _position = 0; NamespaceEntry _ne; { moveToNext(); } public boolean hasNext() { return _ne != null; } public Object next() { if (_position == _size + 2) { throw new NoSuchElementException(); } final String prefix = _ne.prefix; moveToNext(); return prefix; } public void remove() { throw new UnsupportedOperationException(); } private final void moveToNext() { while (++_position < _size + 2) { _ne = _inScopeNamespaces[_position]; if (_ne != null && _namespaceName.equals(_ne.namespaceName)) { return; } } _ne = null; } }; } }