blob: 9f62b78323c8f208b7eee5695e69904740f3f1fe [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
* David Carver (Intalio) - bug 300434 - Make inner classes static where possible
*******************************************************************************/
package org.eclipse.wst.sse.core.internal.text;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
public class TextRegionListImpl implements ITextRegionList {
static private class NullIterator implements Iterator {
public NullIterator() {
}
public boolean hasNext() {
return false;
}
public Object next() {
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$
}
}
private static class RegionIterator implements Iterator {
private ITextRegion[] fIteratorRegions;
private int index = -1;
private int maxindex = -1;
public RegionIterator(ITextRegion[] regions) {
fIteratorRegions = regions;
maxindex = fIteratorRegions.length - 1;
}
public boolean hasNext() {
return index < maxindex;
}
public Object next() {
if (!(index < maxindex))
throw new NoSuchElementException();
return fIteratorRegions[++index];
}
public void remove() {
if (index < 0) {
// next() has never been called
throw new IllegalStateException("can not remove regions without prior invocation of next()"); //$NON-NLS-1$
}
throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$
}
}
private final static int growthConstant = 2;
private ITextRegion[] fRegions;
private int fRegionsCount = 0;
public TextRegionListImpl() {
super();
}
public TextRegionListImpl(ITextRegionList regionList) {
this();
fRegions = (ITextRegion[]) regionList.toArray().clone();
fRegionsCount = fRegions.length;
}
public boolean add(ITextRegion region) {
if (region == null)
return false;
ensureCapacity(fRegionsCount + 1);
fRegions[fRegionsCount++] = region;
return true;
}
public boolean addAll(int insertPos, ITextRegionList newRegionList) {
// beginning of list is 0 to insertPos-1
// remainder of list is insertPos to fRegionsCount
// resulting total will be be fRegionsCount + newRegions.size()
if (insertPos < 0 || insertPos > fRegionsCount) {
throw new ArrayIndexOutOfBoundsException(insertPos);
}
int newRegionListSize = newRegionList.size();
ensureCapacity(fRegionsCount + newRegionListSize);
int numMoved = fRegionsCount - insertPos;
if (numMoved > 0)
System.arraycopy(fRegions, insertPos, fRegions, insertPos + newRegionListSize, numMoved);
if (newRegionList instanceof TextRegionListImpl && ((TextRegionListImpl) newRegionList).fRegions != null) {
System.arraycopy(((TextRegionListImpl) newRegionList).fRegions, 0, fRegions, insertPos, newRegionListSize);
}
else {
for (int i = 0; i < newRegionListSize; i++) {
fRegions[insertPos++] = newRegionList.get(i);
}
}
fRegionsCount += newRegionListSize;
return newRegionListSize != 0;
}
public void clear() {
// note: size of array is not reduced!
fRegionsCount = 0;
}
private void ensureCapacity(int needed) {
if (fRegions == null) {
// first time
fRegions = new ITextRegion[needed];
return;
}
int oldLength = fRegions.length;
if (oldLength < needed) {
ITextRegion[] oldAdapters = fRegions;
ITextRegion[] newAdapters = new ITextRegion[needed + growthConstant];
System.arraycopy(oldAdapters, 0, newAdapters, 0, fRegionsCount);
fRegions = newAdapters;
}
}
public ITextRegion get(int index) {
// fRegionCount may not equal fRegions.length
if (index < 0 || index >= fRegionsCount) {
throw new ArrayIndexOutOfBoundsException(index);
}
return fRegions[index];
}
public int indexOf(ITextRegion region) {
int result = -1;
if (region != null) {
if (fRegions != null) {
for (int i = 0; i < fRegions.length; i++) {
if (region.equals(fRegions[i])) {
result = i;
break;
}
}
}
}
return result;
}
public boolean isEmpty() {
return fRegionsCount == 0;
}
public Iterator iterator() {
if (size() == 0) {
return new NullIterator();
} else {
return new RegionIterator(toArray());
}
}
public ITextRegion remove(int index) {
// much more efficient ways to implement this, but
// I doubt if called often
ITextRegion oneToRemove = get(index);
remove(oneToRemove);
return oneToRemove;
}
public void remove(ITextRegion a) {
if (fRegions == null || a == null)
return;
int newIndex = 0;
ITextRegion[] newRegions = new ITextRegion[fRegionsCount];
int oldRegionCount = fRegionsCount;
boolean found = false;
for (int oldIndex = 0; oldIndex < oldRegionCount; oldIndex++) {
ITextRegion candidate = fRegions[oldIndex];
if (a == candidate) {
fRegionsCount--;
found = true;
} else
newRegions[newIndex++] = fRegions[oldIndex];
}
if (found)
fRegions = newRegions;
}
public void removeAll(ITextRegionList regionList) {
// much more efficient ways to implement this, but
// I doubt if called often
if (regionList != null) {
for (int i = 0; i < regionList.size(); i++) {
this.remove(regionList.get(i));
}
}
}
public int size() {
return fRegionsCount;
}
public ITextRegion[] toArray() {
// return "clone" of internal array
ITextRegion[] newArray = new ITextRegion[fRegionsCount];
System.arraycopy(fRegions, 0, newArray, 0, fRegionsCount);
return newArray;
}
public void trimToSize() {
if (fRegions.length > fRegionsCount) {
ITextRegion[] newRegions = new ITextRegion[fRegionsCount];
System.arraycopy(fRegions, 0, newRegions, 0, fRegionsCount);
fRegions = newRegions;
}
}
}