| /******************************************************************************* |
| * 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; |
| } |
| } |
| |
| } |