| /******************************************************************************* |
| * Copyright (c) 2002, 2013 Object Factory Inc. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Object Factory Inc. - Initial implementation |
| *******************************************************************************/ |
| package org.eclipse.ant.internal.ui.dtd.util; |
| |
| import java.util.Comparator; |
| import java.util.Iterator; |
| |
| import com.ibm.icu.text.MessageFormat; |
| |
| /** |
| * @author Bob Foster |
| */ |
| public class SortedMap implements FactoryObject { |
| |
| private SortedSet fSet; |
| private IMapHolder fHolder; |
| private SortedMap fNext; |
| |
| public SortedMap(IMapHolder holder, Comparator<Object> comp) { |
| fHolder = holder; |
| fSet = new SortedSet(holder, comp); |
| } |
| |
| public SortedMap(Comparator<Object> comp) { |
| fSet = new SortedSet(comp); |
| } |
| |
| public SortedMap(IMapHolder holder) { |
| fHolder = holder; |
| fSet = new SortedSet(holder); |
| } |
| |
| public SortedMap() { |
| fSet = new SortedSet(); |
| } |
| |
| public void setMapHolder(IMapHolder holder) { |
| fHolder = holder; |
| fSet.setKeyHolder(holder); |
| } |
| |
| public void setComparator(Comparator<Object> comp) { |
| fSet.setComparator(comp); |
| } |
| |
| public boolean containsKey(Object key) { |
| return fSet.contains(key); |
| } |
| |
| public boolean containsKeyIdentity(Object key) { |
| return fSet.containsIdentity(key); |
| } |
| |
| public Object put(Object key, Object val) { |
| Object[] values = fHolder.getValues(); |
| int index = fSet.indexOf(key); |
| Object result = index >= 0 && values != null ? values[index] : null; |
| |
| int i = fSet.internalAdd(key, false); |
| if (i >= 0) |
| internalPut(i, val); |
| return result; |
| } |
| |
| protected void internalPut(int i, Object val) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) { |
| values = new Object[1]; |
| values[0] = val; |
| return; |
| } |
| |
| Object[] tmp = new Object[values.length + 1]; |
| System.arraycopy(values, 0, tmp, 0, i); |
| tmp[i] = val; |
| System.arraycopy(values, i, tmp, i + 1, values.length - i); |
| fHolder.setValues(tmp); |
| } |
| |
| public int putAlways(Object key, Object val) { |
| int i = fSet.internalAdd(key, true); |
| internalPut(i, val); |
| return i; |
| } |
| |
| public void append(Object key, Object val) { |
| Object[] values = fHolder.getValues(); |
| int len = values != null ? values.length : 0; |
| fSet.internalAdd(len, key); |
| internalPut(len, val); |
| } |
| |
| public Object get(Object key) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) |
| return null; |
| int i = fSet.indexOf(key); |
| if (i >= 0) |
| return values[i]; |
| return null; |
| } |
| |
| public Object getIdentity(Object key) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) |
| return null; |
| int i = fSet.indexOfIdentity(key); |
| if (i >= 0) |
| return values[i]; |
| return null; |
| } |
| |
| public Object[] keys() { |
| return fSet.members(); |
| } |
| |
| public Object[] values() { |
| Object[] values = fHolder.getValues(); |
| if (values == null) |
| return new Object[0]; |
| return values; |
| } |
| |
| public Iterator<?> keyIterator() { |
| return new ArrayIterator(); |
| } |
| |
| public Iterator<?> valueIterator() { |
| return new ArrayIterator(); |
| } |
| |
| private class ArrayIterator implements Iterator<Object> { |
| private int fIndex; |
| |
| public ArrayIterator() { |
| fIndex = -1; |
| } |
| |
| @Override |
| public boolean hasNext() { |
| Object[] array = SortedMap.this.fHolder.getKeys(); |
| if (array == null) |
| return false; |
| return fIndex + 1 < array.length; |
| } |
| |
| @Override |
| public Object next() { |
| Object[] array = SortedMap.this.fHolder.getKeys(); |
| if (array == null) |
| throw new IllegalStateException(AntDTDUtilMessages.SortedMap_next___called_for_empty_array_1); |
| return array[++fIndex]; |
| } |
| |
| @Override |
| public void remove() { |
| SortedMap.this.remove(fIndex); |
| --fIndex; |
| } |
| |
| } |
| |
| public void remove(int i) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) { |
| throw new IllegalArgumentException(MessageFormat.format(AntDTDUtilMessages.SortedMap_remove__0___in_empty_map_2, new Object[] { |
| Integer.toString(i) })); |
| } |
| fSet.remove(i); |
| Object[] tmp = new Object[values.length - 1]; |
| System.arraycopy(values, 0, tmp, 0, i); |
| System.arraycopy(values, i + 1, tmp, i, values.length - i - 1); |
| fHolder.setValues(tmp); |
| } |
| |
| public Object remove(Object obj) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) |
| return null; |
| int i = fSet.indexOf(obj); |
| if (i >= 0) { |
| Object tmp = values[i]; |
| fSet.remove(i); |
| remove(i); |
| return tmp; |
| } |
| return null; |
| } |
| |
| public Object removeIdentity(Object obj) { |
| Object[] values = fHolder.getValues(); |
| if (values == null) |
| return null; |
| int i = fSet.indexOfIdentity(obj); |
| if (i >= 0) { |
| Object tmp = values[i]; |
| fSet.remove(i); |
| remove(i); |
| return tmp; |
| } |
| return null; |
| } |
| |
| public int size() { |
| return fSet.size(); |
| } |
| |
| public int keyIndex(Object key) { |
| return fSet.indexOf(key); |
| } |
| |
| public void merge(SortedMap other) { |
| Object[] values = fHolder.getValues(); |
| Object[] keys = fHolder.getKeys(); |
| Object[] othervalues = other.fHolder.getValues(); |
| Object[] otherkeys = other.fHolder.getKeys(); |
| if (otherkeys == null) |
| return; |
| if (keys == null) { |
| fHolder.setKeys(otherkeys); |
| fHolder.setValues(othervalues); |
| return; |
| } |
| int ithis = 0, iother = 0, i = 0; |
| int mthis = keys.length, mother = otherkeys.length; |
| Object[] ktmp = new Object[mthis + mother]; |
| Object[] vtmp = new Object[mthis + mother]; |
| while (ithis < mthis && iother < mother) { |
| int comp = fSet.fComp.compare(keys[ithis], otherkeys[iother]); |
| if (comp <= 0) { |
| vtmp[i] = values[ithis]; |
| ktmp[i++] = keys[ithis++]; |
| } else { |
| vtmp[i] = othervalues[iother]; |
| ktmp[i++] = otherkeys[iother++]; |
| } |
| } |
| while (ithis < mthis) { |
| vtmp[i] = values[ithis]; |
| ktmp[i++] = keys[ithis++]; |
| } |
| while (iother < mother) { |
| vtmp[i] = othervalues[iother]; |
| ktmp[i++] = otherkeys[iother++]; |
| } |
| fHolder.setKeys(ktmp); |
| fHolder.setValues(vtmp); |
| } |
| |
| @Override |
| public FactoryObject next() { |
| return fNext; |
| } |
| |
| @Override |
| public void next(FactoryObject next) { |
| fNext = (SortedMap) next; |
| } |
| } |