+The GapList class is a java.util.List
implementation
+similar to java.util.ArrayList
but containing a gap in its underlying
+array. After a first modification at a particular index
+the subsequent modifications around that index are cheap.
+
+The class is suitable for storage of any elements related to editing
+such as positions, elements, views etc.
+
+The PriorityMutex is a simple mutex implementation
+allowing to find out that a priority thread (by default Event Dispatch Thread)
+is waiting to enter the mutex.
+
+It's used e.g. in editor's view hierarchy or in editor fold hierarchy.
+
+GapList-based element implementation suitable for line elements +and any other branch element types. +
+ + ++OpenIDE-Module-Module-Dependencies: org.netbeans.modules.editor.util/1 > @SPECIFICATION-VERSION@ ++
+ No.
+ The present classes were repackaged from org.netbeans.modules.editor.util + into org.netbeans.lib.editor.util package to fulfil the editor module + split proposal #51486 + according to which the editor classes independent of the NB IDE + should be placed under org.netbeans.lib package. +
+This document lists changes made to the Editor Utilities
+API. Please ask on the dev@openide.netbeans.org
mailing list
+if you have any questions about the details of a
+change, or are wondering how to convert existing code to be compatible.
Most module authors should start by reading the Upgrade +Guide for the current release.
+ + + +@FOOTER@
+ + +gapStart
+ * till gapStart + gapLength - 1
.
+ */
+ private transient Object elementData[];
+
+ /**
+ * The start of the gap in the elementData array.
+ */
+ private int gapStart;
+
+ /**
+ * Length of the gap in the elementData array starting at gapStart.
+ */
+ private int gapLength;
+
+ /**
+ * Constructs an empty list with the specified initial capacity.
+ *
+ * @param initialCapacity the initial capacity of the list.
+ * @exception IllegalArgumentException if the specified initial capacity
+ * is negative
+ */
+ public GapList(int initialCapacity) {
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException("Illegal Capacity: " // NOI18N
+ + initialCapacity);
+ }
+ this.elementData = new Object[initialCapacity];
+ this.gapLength = initialCapacity;
+ }
+
+ /**
+ * Constructs an empty list.
+ */
+ public GapList() {
+ elementData = EMPTY_ELEMENT_ARRAY;
+ }
+
+ /**
+ * Constructs a list containing the elements of the specified
+ * collection, in the order they are returned by the collection's
+ * iterator. The GapList instance has an initial capacity of
+ * 110% the size of the specified collection.
+ *
+ * @param c the collection whose elements are to be placed into this list.
+ * @throws NullPointerException if the specified collection is null.
+ */
+ public GapList(Collection c) {
+ int size = c.size();
+ // Allow 10% room for growth
+ elementData = new Object[
+ (int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
+ c.toArray(elementData);
+ this.gapStart = size;
+ this.gapLength = elementData.length - size;
+ }
+
+ /**
+ * Trims the capacity of this GapList instance to be the
+ * list's current size. An application can use this operation to minimize
+ * the storage of an GapList instance.
+ */
+ public void trimToSize() {
+ modCount++;
+ if (gapLength > 0) {
+ int newLength = elementData.length - gapLength;
+ Object[] newElementData = new Object[newLength];
+ copyAllData(newElementData);
+ elementData = newElementData;
+ // Leave gapStart as is
+ gapLength = 0;
+ }
+ }
+
+ /**
+ * Increases the capacity of this GapList instance, if
+ * necessary, to ensure that it can hold at least the number of elements
+ * specified by the minimum capacity argument.
+ *
+ * @param minCapacity the desired minimum capacity.
+ */
+ public void ensureCapacity(int minCapacity) {
+ modCount++; // expected to always increment modCount - see add() operations
+ int oldCapacity = elementData.length;
+ if (minCapacity > oldCapacity) {
+ int newCapacity = (oldCapacity * 3)/2 + 1;
+ if (newCapacity < minCapacity) {
+ newCapacity = minCapacity;
+ }
+ int gapEnd = gapStart + gapLength;
+ int afterGapLength = (oldCapacity - gapEnd);
+ // Must ensure the gap will not be logically moved
+ // (would have to call movedAbove/BeforeGapUpdate() methods)
+ int newGapEnd = newCapacity - afterGapLength;
+ Object[] newElementData = new Object[newCapacity];
+ System.arraycopy(elementData, 0, newElementData, 0, gapStart);
+ System.arraycopy(elementData, gapEnd, newElementData, newGapEnd, afterGapLength);
+ elementData = newElementData;
+ gapLength = newGapEnd - gapStart;
+ }
+ }
+
+ /**
+ * Returns the number of elements in this list.
+ *
+ * @return the number of elements in this list.
+ */
+ public int size() {
+ return elementData.length - gapLength;
+ }
+
+ /**
+ * Tests if this list has no elements.
+ *
+ * @return true if this list has no elements;
+ * false otherwise.
+ */
+ public boolean isEmpty() {
+ return (elementData.length == gapLength);
+ }
+
+ /**
+ * Returns true if this list contains the specified element.
+ *
+ * @param elem element whose presence in this List is to be tested.
+ * @return true
if the specified element is present;
+ * false
otherwise.
+ */
+ public boolean contains(Object elem) {
+ return indexOf(elem) >= 0;
+ }
+
+ /**
+ * Searches for the first occurence of the given argument, testing
+ * for equality using the equals method.
+ *
+ * @param elem an object.
+ * @return the index of the first occurrence of the argument in this
+ * list; returns -1 if the object is not found.
+ * @see Object#equals(Object)
+ */
+ public int indexOf(Object elem) {
+ if (elem == null) {
+ int i = 0;
+ while (i < gapStart) {
+ if (elementData[i] == null) {
+ return i;
+ }
+ i++;
+ }
+ i += gapLength;
+ int elementDataLength = elementData.length;
+ while (i < elementDataLength) {
+ if (elementData[i] == null) {
+ return i;
+ }
+ i++;
+ }
+
+ } else { // elem not null
+ int i = 0;
+ while (i < gapStart) {
+ if (elem.equals(elementData[i])) {
+ return i;
+ }
+ i++;
+ }
+ i += gapLength;
+ int elementDataLength = elementData.length;
+ while (i < elementDataLength) {
+ if (elem.equals(elementData[i])) {
+ return i;
+ }
+ i++;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the index of the last occurrence of the specified object in
+ * this list.
+ *
+ * @param elem the desired element.
+ * @return the index of the last occurrence of the specified object in
+ * this list; returns -1 if the object is not found.
+ */
+ public int lastIndexOf(Object elem) {
+ if (elem == null) {
+ int i = elementData.length - 1;
+ int gapEnd = gapStart + gapLength;
+ while (i >= gapEnd) {
+ if (elementData[i] == null) {
+ return i;
+ }
+ i--;
+ }
+ i -= gapLength;
+ while (i >= 0) {
+ if (elementData[i] == null) {
+ return i;
+ }
+ i--;
+ }
+
+ } else { // elem not null
+ int i = elementData.length - 1;
+ int gapEnd = gapStart + gapLength;
+ while (i >= gapEnd) {
+ if (elem.equals(elementData[i])) {
+ return i;
+ }
+ i--;
+ }
+ i -= gapLength;
+ while (i >= 0) {
+ if (elem.equals(elementData[i])) {
+ return i;
+ }
+ i--;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns a shallow copy of this GapList instance. (The
+ * elements themselves are not copied.)
+ *
+ * @return a clone of this GapList instance.
+ */
+ public Object clone() {
+ try {
+ GapList clonedList = (GapList)super.clone();
+ int size = size();
+ Object[] clonedElementData = new Object[size];
+ copyAllData(clonedElementData);
+ clonedList.elementData = clonedElementData;
+ // Will retain gapStart - would have to call moved*() otherwise
+ clonedList.gapStart = size;
+ clonedList.resetModCount();
+ return clonedList;
+
+ } catch (CloneNotSupportedException e) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
+
+ public void copyItems(int srcStartIndex, int srcEndIndex,
+ Object[] dest, int destIndex) {
+
+ if (srcStartIndex < 0 || srcEndIndex < srcStartIndex || srcEndIndex > size()) {
+ throw new IndexOutOfBoundsException("srcStartIndex=" + srcStartIndex // NOI18N
+ + ", srcEndIndex=" + srcEndIndex + ", size()=" + size()); // NOI18N
+ }
+
+ if (srcEndIndex < gapStart) { // fully below gap
+ System.arraycopy(elementData, srcStartIndex,
+ dest, destIndex, srcEndIndex - srcStartIndex);
+
+ } else { // above gap or spans the gap
+ if (srcStartIndex >= gapStart) { // fully above gap
+ System.arraycopy(elementData, srcStartIndex + gapLength, dest, destIndex,
+ srcEndIndex - srcStartIndex);
+
+ } else { // spans gap
+ int beforeGap = gapStart - srcStartIndex;
+ System.arraycopy(elementData, srcStartIndex, dest, destIndex, beforeGap);
+ System.arraycopy(elementData, gapStart + gapLength, dest, destIndex + beforeGap,
+ srcEndIndex - srcStartIndex - beforeGap);
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list
+ * in the correct order.
+ *
+ * @return an array containing all of the elements in this list
+ * in the correct order.
+ */
+ public Object[] toArray() {
+ int size = size();
+ Object[] result = new Object[size];
+ copyAllData(result);
+ return result;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this list in the
+ * correct order; the runtime type of the returned array is that of the
+ * specified array. If the list fits in the specified array, it is
+ * returned therein. Otherwise, a new array is allocated with the runtime
+ * type of the specified array and the size of this list.
+ *
+ * If the list fits in the specified array with room to spare (i.e., the
+ * array has more elements than the list), the element in the array
+ * immediately following the end of the collection is set to
+ * null. This is useful in determining the length of the list
+ * only if the caller knows that the list does not contain any
+ * null elements.
+ *
+ * @param a the array into which the elements of the list are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose.
+ * @return an array containing the elements of the list.
+ * @throws ArrayStoreException if the runtime type of a is not a supertype
+ * of the runtime type of every element in this list.
+ */
+ public Object[] toArray(Object a[]) {
+ int size = size();
+ if (a.length < size) {
+ a = (Object[])java.lang.reflect.Array.newInstance(
+ a.getClass().getComponentType(), size);
+ }
+ copyAllData(a);
+ if (a.length > size)
+ a[size] = null;
+
+ return a;
+ }
+
+ // Positional Access Operations
+
+ /**
+ * Returns the element at the specified position in this list.
+ *
+ * @param index index of element to return.
+ * @return the element at the specified position in this list.
+ * @throws IndexOutOfBoundsException if index is out of range (index
+ * < 0 || index >= size()).
+ */
+ public Object get(int index) {
+ // rangeCheck(index) not necessary - would fail with AIOOBE anyway
+ return elementData[(index < gapStart) ? index : (index + gapLength)];
+ }
+
+ /**
+ * Replaces the element at the specified position in this list with
+ * the specified element.
+ *
+ * @param index index of element to replace.
+ * @param element element to be stored at the specified position.
+ * @return the element previously at the specified position.
+ * @throws IndexOutOfBoundsException if index out of range
+ * (index < 0 || index >= size()).
+ */
+ public Object set(int index, Object element) {
+ // rangeCheck(index) not necessary - would fail with AIOOBE anyway
+ if (index >= gapStart) {
+ index += gapLength;
+ }
+ Object oldValue = elementData[index];
+ elementData[index] = element;
+ return oldValue;
+ }
+
+ /**
+ * Appends the specified element to the end of this list.
+ *
+ * @param o element to be appended to this list.
+ * @return true (as per the general contract of Collection.add).
+ */
+ public boolean add(Object o) {
+ add(size(), o);
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in this
+ * list. Shifts the element currently at that position (if any) and
+ * any subsequent elements to the right (adds one to their indices).
+ *
+ * @param index index at which the specified element is to be inserted.
+ * @param element element to be inserted.
+ * @throws IndexOutOfBoundsException if index is out of range
+ * (index < 0 || index > size()).
+ */
+ public void add(int index, Object element) {
+ int size = size();
+ if (index > size || index < 0) {
+ throw new IndexOutOfBoundsException(
+ "Index: " + index + ", Size: " + size); // NOI18N
+ }
+
+ ensureCapacity(size + 1); // Increments modCount!!
+ moveGap(index);
+
+ elementData[gapStart++] = element;
+ gapLength--;
+ }
+
+ /**
+ * Appends all of the elements in the specified Collection to the end of
+ * this list, in the order that they are returned by the
+ * specified Collection's Iterator. The behavior of this operation is
+ * undefined if the specified Collection is modified while the operation
+ * is in progress. (This implies that the behavior of this call is
+ * undefined if the specified Collection is this list, and this
+ * list is nonempty.)
+ *
+ * @param c the elements to be inserted into this list.
+ * @return true if this list changed as a result of the call.
+ * @throws NullPointerException if the specified collection is null.
+ */
+ public boolean addAll(Collection c) {
+ return addAll(size(), c);
+ }
+
+ /**
+ * Inserts all of the elements in the specified Collection into this
+ * list, starting at the specified position. Shifts the element
+ * currently at that position (if any) and any subsequent elements to
+ * the right (increases their indices). The new elements will appear
+ * in the list in the order that they are returned by the
+ * specified Collection's iterator.
+ *
+ * @param index index at which to insert first element
+ * from the specified collection.
+ * @param c elements to be inserted into this list.
+ * @return true if this list changed as a result of the call.
+ * @throws IndexOutOfBoundsException if index out of range (index
+ * < 0 || index > size()).
+ * @throws NullPointerException if the specified Collection is null.
+ */
+ public boolean addAll(int index, Collection c) {
+ return addArray(index, c.toArray());
+ }
+
+ /*
+ * Inserts all elements from the given array into this list, starting
+ * at the given index.
+ *
+ * @param index index at which to insert first element from the array.
+ * @param elements array of elements to insert.
+ */
+ public boolean addArray(int index, Object[] elements) {
+ return addArray(index, elements, 0, elements.length);
+ }
+
+ /**
+ * Inserts elements from the given array into this list, starting
+ * at the given index.
+ *
+ * @param index index at which to insert first element.
+ * @param elements array of elements from which to insert elements.
+ * @param off offset in the elements pointing to first element to copy.
+ * @param len number of elements to copy from the elements array.
+ */
+ public boolean addArray(int index, Object[] elements, int off, int len) {
+ int size = size();
+ if (index > size || index < 0) {
+ throw new IndexOutOfBoundsException(
+ "Index: " + index + ", Size: " + size); // NOI18N
+ }
+
+ ensureCapacity(size + len); // Increments modCount
+
+ moveGap(index);
+ System.arraycopy(elements, off, elementData, gapStart, len);
+ gapStart += len;
+ gapLength -= len;
+
+ return (len != 0);
+ }
+
+
+
+ /**
+ * Removes all of the elements from this list. The list will
+ * be empty after this call returns.
+ */
+ public void clear() {
+ removeRange(0, size());
+ }
+
+ /**
+ * Removes the element at the specified position in this list.
+ * Shifts any subsequent elements to the left (subtracts one from their
+ * indices).
+ *
+ * @param index the index of the element to removed.
+ * @return the element that was removed from the list.
+ * @throws IndexOutOfBoundsException if index out of range (index
+ * < 0 || index >= size()).
+ */
+ public Object remove(int index) {
+ int size = size();
+ if (index >= size || index < 0) {
+ throw new IndexOutOfBoundsException(
+ "remove(): Index: " + index + ", Size: " + size); // NOI18N
+ }
+
+ modCount++;
+ moveGap(index + 1); // if previous were adds() - this should be no-op
+ Object oldValue = elementData[index];
+ removeUpdate(index, elementData, index, index + 1);
+ elementData[index] = null;
+ gapStart--;
+ gapLength++;
+
+ return oldValue;
+ }
+
+ /**
+ * Removes elements at the given index.
+ *
+ * @param index index of the first element to be removed.
+ * @param count number of elements to remove.
+ */
+ public void remove(int index, int count) {
+ int toIndex = index + count;
+ if (index < 0 || toIndex < index || toIndex > size()) {
+ throw new IndexOutOfBoundsException("index=" + index // NOI18N
+ + ", count=" + count + ", size()=" + size()); // NOI18N
+ }
+ removeRange(index, toIndex);
+ }
+
+ /**
+ * Removes from this List all of the elements whose index is between
+ * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
+ * elements to the left (reduces their index).
+ * This call shortens the list by (toIndex - fromIndex) elements.
+ * (If toIndex==fromIndex, this operation has no effect.)
+ *
+ * @param fromIndex index of first element to be removed.
+ * @param toIndex index after last element to be removed.
+ */
+ protected void removeRange(int fromIndex, int toIndex) {
+ modCount++;
+ if (fromIndex == toIndex) {
+ return;
+ }
+
+ int removeCount = toIndex - fromIndex;
+ if (fromIndex >= gapStart) { // completely over gap
+ // Move gap to the start of the removed area
+ // (this should be the minimum necessary count of elements moved)
+ moveGap(fromIndex);
+
+ // Allow GC of removed items
+ fromIndex += gapLength; // begining of abandoned area
+ toIndex += gapLength;
+ removeUpdate(fromIndex - gapLength, elementData, fromIndex, toIndex);
+ while (fromIndex < toIndex) {
+ elementData[fromIndex] = null;
+ fromIndex++;
+ }
+
+ } else { // completely below gap or spans the gap
+ if (toIndex <= gapStart) {
+ // Move gap to the end of the removed area
+ // (this should be the minimum necessary count of elements moved)
+ moveGap(toIndex);
+ gapStart = fromIndex;
+ // Call removeUpdate() for items that will be physically removed soon
+ removeUpdate(fromIndex, elementData, fromIndex, toIndex);
+
+ } else { // spans gap: gapStart > fromIndex but gapStart - fromIndex < removeCount
+ removeUpdate(fromIndex, elementData, fromIndex, gapStart);
+ // Allow GC of removed items
+ for (int clearIndex = fromIndex; clearIndex < gapStart; clearIndex++) {
+ elementData[clearIndex] = null;
+ }
+
+ fromIndex = gapStart + gapLength; // part above the gap
+ gapStart = toIndex - removeCount; // original value of fromIndex
+ toIndex += gapLength;
+ removeUpdate(gapStart, elementData, fromIndex, toIndex);
+ }
+
+ // Allow GC of removed items
+ while (fromIndex < toIndex) {
+ elementData[fromIndex++] = null;
+ }
+
+ }
+
+ gapLength += removeCount;
+ }
+
+ /**
+ * Called prior physical removing of the data from the list.
+ *
+ * The implementation can possibly update the elements in the removed area.
+ *
+ * After this method finishes the whole removed area will be
+ * null
-ed.
+ *
+ * @param index index in the list of the first item being removed.
+ * @param data array of objects from which the data are being removed.
+ * The next two parameters define the indexes at which the elements
+ * can be updated.
+ *
+ * Absolutely no changes should be done outside of
+ * <startOff, endOff)
area.
+ * @param startOff offset in the data array of the first element that
+ * will be removed.
+ * @param endOff offset in the data array following the last item that will
+ * be removed.
+ */
+ protected void removeUpdate(int index, Object[] data, int startOff, int endOff) {
+ }
+
+ /*
+ protected void movedAboveGapUpdate(Object[] array, int index, int count) {
+ }
+
+ protected void movedBelowGapUpdate(Object[] array, int index, int count) {
+ }
+ */
+
+ private void moveGap(int index) {
+ if (index == gapStart) {
+ return; // do nothing
+ }
+
+ if (index < gapStart) { // move gap down
+ int moveSize = gapStart - index;
+ System.arraycopy(elementData, index, elementData,
+ gapStart + gapLength - moveSize, moveSize);
+ clearEmpty(index, Math.min(moveSize, gapLength));
+ gapStart = index;
+ // movedAboveGapUpdate(elementData, gapStart + gapLength, moveSize);
+
+ } else { // above gap
+ int gapEnd = gapStart + gapLength;
+ int moveSize = index - gapStart;
+ System.arraycopy(elementData, gapEnd, elementData, gapStart, moveSize);
+ if (index < gapEnd) {
+ clearEmpty(gapEnd, moveSize);
+ } else {
+ clearEmpty(index, gapLength);
+ }
+ // movedBelowGapUpdate(elementData, gapStart, moveSize);
+ gapStart += moveSize;
+ }
+ }
+
+ private void copyAllData(Object[] toArray) {
+ if (gapLength != 0) {
+ int gapEnd = gapStart + gapLength;
+ System.arraycopy(elementData, 0, toArray, 0, gapStart);
+ System.arraycopy(elementData, gapEnd, toArray, gapStart,
+ elementData.length - gapEnd);
+ } else { // no gap => single copy of everything
+ System.arraycopy(elementData, 0, toArray, 0, elementData.length);
+ }
+ }
+
+ private void clearEmpty(int index, int length) {
+ while (--length >= 0) {
+ elementData[index++] = null; // allow GC
+ }
+ }
+
+ private void resetModCount() {
+ modCount = 0;
+ }
+
+ /**
+ * Save the state of the GapList instance to a stream (that
+ * is, serialize it).
+ *
+ * @serialData The length of the array backing the GapList
+ * instance is emitted (int), followed by all of its elements
+ * (each an Object) in the proper order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException{
+ // Write out element count, and any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out array length
+ s.writeInt(elementData.length);
+
+ // Write out all elements in the proper order.
+ int i = 0;
+ while (i < gapStart) {
+ s.writeObject(elementData[i]);
+ i++;
+ }
+ i += gapLength;
+ int elementDataLength = elementData.length;
+ while (i < elementDataLength) {
+ s.writeObject(elementData[i]);
+ i++;
+ }
+ }
+
+ /**
+ * Reconstitute the GapList instance from a stream (that is,
+ * deserialize it).
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in size, and any hidden stuff
+ s.defaultReadObject();
+
+ // Read in array length and allocate array
+ int arrayLength = s.readInt();
+ elementData = new Object[arrayLength];
+
+ // Read in all elements in the proper order.
+ int i = 0;
+ while (i < gapStart) {
+ elementData[i] = s.readObject();
+ i++;
+ }
+ i += gapLength;
+ int elementDataLength = elementData.length;
+ while (i < elementDataLength) {
+ elementData[i] = s.readObject();
+ i++;
+ }
+ }
+
+ /**
+ * Internal consistency check.
+ */
+ void consistencyCheck() {
+ if (gapStart < 0 || gapLength < 0
+ || gapStart + gapLength > elementData.length
+ ) {
+ consistencyError("Inconsistent gap"); // NOI18N
+ }
+
+ // Check whether the whole gap contains only nulls
+ for (int i = gapStart + gapLength - 1; i >= gapStart; i--) {
+ if (elementData[i] != null) {
+ consistencyError("Non-null value at raw-index i"); // NOI18N
+ }
+ }
+ }
+
+ private void consistencyError(String s) {
+ throw new IllegalStateException(s + ": " + toStringInternals()); // NOI18N
+ }
+
+ String toStringInternals() {
+ return "elementData.length=" + elementData.length // NOI18N
+ + ", gapStart=" + gapStart + ", gapLength=" + gapLength; // NOI18N
+ }
+
+}
Index: editor/util/src/org/netbeans/lib/editor/util/PriorityMutex.java
===================================================================
RCS file: editor/util/src/org/netbeans/lib/editor/util/PriorityMutex.java
diff -N editor/util/src/org/netbeans/lib/editor/util/PriorityMutex.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ editor/util/src/org/netbeans/lib/editor/util/PriorityMutex.java 21 Mar 2005 17:31:25 -0000
@@ -0,0 +1,147 @@
+/*
+ * Sun Public License Notice
+ *
+ * The contents of this file are subject to the Sun Public License
+ * Version 1.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ * http://www.sun.com/
+ *
+ * The Original Code is NetBeans. The Initial Developer of the Original
+ * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ */
+
+package org.netbeans.lib.editor.util;
+
+/**
+ * Mutex that allows only one thread to proceed
+ * other threads must wait until that one finishes.
+ *
+ * The thread that "holds" the mutex (has the mutex access granted)
+ * may reenter the mutex arbitrary number of times
+ * (just increasing a "depth" of the locking).
+ *
+ * If the priority thread enters waiting on the mutex
+ * then it will get serviced first once the current thread
+ * leaves the mutex.
+ *
+ * @author Miloslav Metelka
+ * @version 1.00
+ */
+
+public class PriorityMutex {
+
+ private Thread lockThread;
+
+ private int lockDepth;
+
+ private Thread waitingPriorityThread;
+
+ /**
+ * Acquire the ownership of the mutex.
+ *
+ *
+ * The following pattern should always be used: + *
+ * mutex.lock(); + * try { + * ... + * } finally { + * mutex.unlock(); + * } + *+ */ + public synchronized void lock() { + Thread thread = Thread.currentThread(); + if (thread != lockThread) { // not nested locking + // Will wait if either there is another thread already holding the lock + // or if there is a priority thread waiting but it's not this thread + while (lockThread != null + || (waitingPriorityThread != null && waitingPriorityThread != thread) + ) { + try { + if (waitingPriorityThread == null && isPriorityThread()) { + waitingPriorityThread = thread; + } + + wait(); + + } catch (InterruptedException e) { + waitingPriorityThread = null; + } + } + + lockThread = thread; + + if (thread == waitingPriorityThread) { + waitingPriorityThread = null; // it's now allowed to enter + } + } + + lockDepth++; + } + + /** + * Release the ownership of the mutex. + * + * @see lock() + */ + public synchronized void unlock() { + if (Thread.currentThread() != lockThread) { + throw new IllegalStateException("Not locker"); // NOI18N + } + + if (--lockDepth == 0) { + lockThread = null; + + notifyAll(); // must all to surely notify waitingPriorityThread too + } + } + + /** + * Can be called by the thread + * that acquired the mutex to check whether there + * is a priority thread (such as AWT event-notification thread) + * waiting. + *
null
+ * if there is currently no thread holding that acquired this mutex.
+ */
+ public final synchronized Thread getLockThread() {
+ return lockThread;
+ }
+
+ /**
+ * Return true if the current thread that is entering this method
+ * is a priority thread
+ * and should be allowed to enter as soon as possible.
+ *
+ *
+ * The default implementation assumes that
+ * {@link javax.swing.SwingUtilities#isEventDispatchThread()}
+ * is a priority thread.
+ *
+ * @return true if the entering thread is a priority thread.
+ */
+ protected boolean isPriorityThread() {
+ return javax.swing.SwingUtilities.isEventDispatchThread();
+ }
+
+}
Index: editor/util/src/org/netbeans/lib/editor/util/swing/ElementUtilities.java
===================================================================
RCS file: editor/util/src/org/netbeans/lib/editor/util/swing/ElementUtilities.java
diff -N editor/util/src/org/netbeans/lib/editor/util/swing/ElementUtilities.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ editor/util/src/org/netbeans/lib/editor/util/swing/ElementUtilities.java 21 Mar 2005 17:31:25 -0000
@@ -0,0 +1,39 @@
+/*
+ * Sun Public License Notice
+ *
+ * The contents of this file are subject to the Sun Public License
+ * Version 1.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ * http://www.sun.com/
+ *
+ * The Original Code is NetBeans. The Initial Developer of the Original
+ * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ */
+
+package org.netbeans.lib.editor.util.swing;
+
+import javax.swing.text.Element;
+
+/**
+ * Various utility methods related to elements.
+ *
+ * @author Miloslav Metelka
+ * @version 1.00
+ */
+
+public final class ElementUtilities {
+
+ private ElementUtilities() {
+ // No instances
+ }
+
+ public static void updateOffsetRange(Element[] elements, int[] offsetRange) {
+ int elementsLength = elements.length;
+ if (elementsLength > 0) {
+ offsetRange[0] = Math.min(offsetRange[0], elements[0].getStartOffset());
+ offsetRange[1] = Math.max(offsetRange[1], elements[elementsLength - 1].getEndOffset());
+ }
+ }
+
+}
Index: editor/util/src/org/netbeans/lib/editor/util/swing/GapBranchElement.java
===================================================================
RCS file: editor/util/src/org/netbeans/lib/editor/util/swing/GapBranchElement.java
diff -N editor/util/src/org/netbeans/lib/editor/util/swing/GapBranchElement.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ editor/util/src/org/netbeans/lib/editor/util/swing/GapBranchElement.java 21 Mar 2005 17:31:25 -0000
@@ -0,0 +1,245 @@
+/*
+ * Sun Public License Notice
+ *
+ * The contents of this file are subject to the Sun Public License
+ * Version 1.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ * http://www.sun.com/
+ *
+ * The Original Code is NetBeans. The Initial Developer of the Original
+ * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ */
+
+package org.netbeans.lib.editor.util.swing;
+
+import javax.swing.text.Element;
+import javax.swing.event.DocumentEvent;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.CannotRedoException;
+import org.netbeans.lib.editor.util.GapList;
+
+/**
+ * Branch element that uses gap list to maintain its child elements.
+ *
+ * @author Miloslav Metelka
+ * @version 1.00
+ */
+
+public abstract class GapBranchElement implements Element {
+
+ protected static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0];
+
+ private GapList children;
+
+ public GapBranchElement() {
+ children = new GapList();
+ }
+
+ public int getElementCount() {
+ return children.size();
+ }
+
+ public Element getElement(int index) {
+ return (Element)children.get(index);
+ }
+
+ public void copyElements(int srcBegin, int srcEnd, Element dst[], int dstBegin) {
+ children.copyItems(srcBegin, srcEnd, dst, dstBegin);
+ }
+
+ /**
+ * Gets the child element index closest to the given offset.
+ * The offset is specified relative to the beginning of the
+ * document. Returns -1
if the
+ * Element
is a leaf, otherwise returns
+ * the index of the Element
that best represents
+ * the given location. Returns 0
if the location
+ * is less than the start offset. Returns
+ * getElementCount() - 1
if the location is
+ * greater than or equal to the end offset.
+ *
+ *
+ * This implementation is in sync with the original
+ * Element.getElementIndex()
specification
+ * but it differs
+ * from AbstractDocument.BranchElement.getElementIndex()
+ * which returns 0 in case it does not have any children.
+ *
+ * This implementation returns -1 in that case because in fact
+ * the element act as a leaf element in such case.
+ *
+ * Nonetheless there should be no difference in functionality
+ * if this implementation is used for line elements
+ * because there is always at least one line element even
+ * for empty doc because of the extra '\n' after the end
+ * of the AbstractDocument-based implementations.
+ *
+ * @param offset the specified offset >= 0
+ * @return the element index >= 0
+ */
+ public int getElementIndex(int offset) {
+ int low = 0;
+ int high = getElementCount() - 1;
+
+ if (high == -1) { // no children => return -1
+ return -1;
+ }
+
+ while (low <= high) {
+ int mid = (low + high) / 2;
+ int elemStartOffset = getElement(mid).getStartOffset();
+
+ if (elemStartOffset < offset) {
+ low = mid + 1;
+ } else if (elemStartOffset > offset) {
+ high = mid - 1;
+ } else { // element starts at offset
+ return mid;
+ }
+ }
+
+ if (high < 0) { // if offset < getElement(0).getStartOffset()
+ high = 0;
+ }
+ return high;
+ }
+
+ public boolean isLeaf() {
+ return false;
+ }
+
+ protected void replace(int index, int removeCount, Element[] addedElems) {
+ if (removeCount > 0) {
+ children.remove(index, removeCount);
+ }
+ if (addedElems != null) {
+ children.addArray(index, addedElems);
+ }
+ }
+
+ /** Get info about DocMarks
. */
+ public String toString() {
+ return children.toString();
+ }
+
+ public class Edit extends AbstractUndoableEdit
+ implements DocumentEvent.ElementChange {
+
+ private int index;
+
+ private Element[] childrenAdded;
+
+ private Element[] childrenRemoved;
+
+ public Edit(int index, Element[] childrenRemoved, Element[] childrenAdded) {
+ this.index = index;
+ this.childrenRemoved = childrenRemoved;
+ this.childrenAdded = childrenAdded;
+ }
+
+ public Element getElement() {
+ return GapBranchElement.this;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public Element[] getChildrenRemoved() {
+ return childrenRemoved;
+ }
+
+ public Element[] getChildrenAdded() {
+ return childrenAdded;
+ }
+
+ public void undo() throws CannotUndoException {
+ super.undo();
+
+ replace(index, childrenAdded.length, childrenRemoved);
+
+ // Switch childrenAdded with childrenRemoved
+ Element[] tmp = childrenRemoved;
+ childrenRemoved = childrenAdded;
+ childrenAdded = tmp;
+ }
+
+ public void redo() throws CannotRedoException {
+ super.redo();
+
+ // Switch childrenAdded with childrenRemoved
+ Element[] tmp = childrenRemoved;
+ childrenRemoved = childrenAdded;
+ childrenAdded = tmp;
+
+ replace(index, childrenRemoved.length, childrenAdded);
+ }
+
+ }
+
+ /**
+ * Extension of {@link GapBranchElement}
+ * that overrides {@link #getElementIndex(int)}
+ * which remembers the last returned element index.
+ */
+ public abstract class LastIndex {
+
+ private int lastReturnedElementIndex;
+
+ /**
+ * Implementation that remembers the last returned element index
+ * and checks the element at the last index when next called.
+ *
+ * This may improve performance if there are typically many repetitive calls
+ * with offset values hitting the last returned element index.
+ */
+ public int getElementIndex(int offset) {
+ int low = 0;
+ int high = getElementCount() - 1;
+
+ if (high == -1) { // no children => return -1
+ return -1;
+ }
+
+ int lastIndex = lastReturnedElementIndex; // make copy to be thread-safe
+ if (lastIndex >= low && lastIndex <= high) {
+ Element lastElem = getElement(lastIndex);
+ int lastElemStartOffset = lastElem.getStartOffset();
+ if (offset >= lastElemStartOffset) {
+ int lastElemEndOffset = lastElem.getEndOffset();
+ if (offset < lastElemEndOffset) { // hit
+ return lastIndex;
+ } else { // above
+ low = lastIndex + 1;
+ }
+ } else { // below lastIndex
+ high = lastIndex - 1;
+ }
+ }
+
+ while (low <= high) {
+ int mid = (low + high) / 2;
+ int elemStartOffset = ((Element)children.get(mid)).getStartOffset();
+
+ if (elemStartOffset < offset) {
+ low = mid + 1;
+ } else if (elemStartOffset > offset) {
+ high = mid - 1;
+ } else { // element starts at offset
+ lastReturnedElementIndex = mid;
+ return mid;
+ }
+ }
+
+ if (high < 0) {
+ high = 0;
+ }
+ lastReturnedElementIndex = high;
+ return high;
+ }
+
+ }
+
+}
Index: editor/util/src/org/netbeans/modules/editor/util/Bundle.properties
===================================================================
RCS file: editor/util/src/org/netbeans/modules/editor/util/Bundle.properties
diff -N editor/util/src/org/netbeans/modules/editor/util/Bundle.properties
--- editor/util/src/org/netbeans/modules/editor/util/Bundle.properties 29 Jun 2004 09:32:13 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,16 +0,0 @@
-# Sun Public License Notice
-#
-# The contents of this file are subject to the Sun Public License
-# Version 1.0 (the "License"). You may not use this file except in
-# compliance with the License. A copy of the License is available at
-# http://www.sun.com/
-#
-# The Original Code is NetBeans. The Initial Developer of the Original
-# Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
-# Microsystems, Inc. All Rights Reserved.
-
-OpenIDE-Module-Name=Editor Utilities
-OpenIDE-Module-Display-Category=Editing
-OpenIDE-Module-Short-Description=Contains various support classes for editor related modules
-OpenIDE-Module-Long-Description=Editor Utilities module contains various utility classes and methods for functionality related to editing
-
Index: editor/util/src/org/netbeans/modules/editor/util/GapList.java
===================================================================
RCS file: editor/util/src/org/netbeans/modules/editor/util/GapList.java
diff -N editor/util/src/org/netbeans/modules/editor/util/GapList.java
--- editor/util/src/org/netbeans/modules/editor/util/GapList.java 18 Aug 2004 17:22:37 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,785 +0,0 @@
-/*
- * Sun Public License Notice
- *
- * The contents of this file are subject to the Sun Public License
- * Version 1.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://www.sun.com/
- *
- * The Original Code is NetBeans. The Initial Developer of the Original
- * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
- * Microsystems, Inc. All Rights Reserved.
- */
-
-package org.netbeans.modules.editor.util;
-
-import java.util.AbstractList;
-import java.util.Collection;
-import java.util.RandomAccess;
-
-/**
- * List implementation that stores items in an array
- * with a gap.
- *
- * @author Miloslav Metelka
- * @version 1.00
- */
-
-public class GapList extends AbstractList
-implements RandomAccess, Cloneable, java.io.Serializable {
-
- private static final Object[] EMPTY_ELEMENT_ARRAY = new Object[0];
-
- /**
- * The array buffer into which the elements are stored.
- *
- * The elements are stored in the whole array except
- * the indexes starting at gapStart
- * till gapStart + gapLength - 1
.
- */
- private transient Object elementData[];
-
- /**
- * The start of the gap in the elementData array.
- */
- private int gapStart;
-
- /**
- * Length of the gap in the elementData array starting at gapStart.
- */
- private int gapLength;
-
- /**
- * Constructs an empty list with the specified initial capacity.
- *
- * @param initialCapacity the initial capacity of the list.
- * @exception IllegalArgumentException if the specified initial capacity
- * is negative
- */
- public GapList(int initialCapacity) {
- if (initialCapacity < 0) {
- throw new IllegalArgumentException("Illegal Capacity: " // NOI18N
- + initialCapacity);
- }
- this.elementData = new Object[initialCapacity];
- this.gapLength = initialCapacity;
- }
-
- /**
- * Constructs an empty list.
- */
- public GapList() {
- elementData = EMPTY_ELEMENT_ARRAY;
- }
-
- /**
- * Constructs a list containing the elements of the specified
- * collection, in the order they are returned by the collection's
- * iterator. The GapList instance has an initial capacity of
- * 110% the size of the specified collection.
- *
- * @param c the collection whose elements are to be placed into this list.
- * @throws NullPointerException if the specified collection is null.
- */
- public GapList(Collection c) {
- int size = c.size();
- // Allow 10% room for growth
- elementData = new Object[
- (int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
- c.toArray(elementData);
- this.gapStart = size;
- this.gapLength = elementData.length - size;
- }
-
- /**
- * Trims the capacity of this GapList instance to be the
- * list's current size. An application can use this operation to minimize
- * the storage of an GapList instance.
- */
- public void trimToSize() {
- modCount++;
- if (gapLength > 0) {
- int newLength = elementData.length - gapLength;
- Object[] newElementData = new Object[newLength];
- copyAllData(newElementData);
- elementData = newElementData;
- // Leave gapStart as is
- gapLength = 0;
- }
- }
-
- /**
- * Increases the capacity of this GapList instance, if
- * necessary, to ensure that it can hold at least the number of elements
- * specified by the minimum capacity argument.
- *
- * @param minCapacity the desired minimum capacity.
- */
- public void ensureCapacity(int minCapacity) {
- modCount++; // expected to always increment modCount - see add() operations
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {
- int newCapacity = (oldCapacity * 3)/2 + 1;
- if (newCapacity < minCapacity) {
- newCapacity = minCapacity;
- }
- int gapEnd = gapStart + gapLength;
- int afterGapLength = (oldCapacity - gapEnd);
- // Must ensure the gap will not be logically moved
- // (would have to call movedAbove/BeforeGapUpdate() methods)
- int newGapEnd = newCapacity - afterGapLength;
- Object[] newElementData = new Object[newCapacity];
- System.arraycopy(elementData, 0, newElementData, 0, gapStart);
- System.arraycopy(elementData, gapEnd, newElementData, newGapEnd, afterGapLength);
- elementData = newElementData;
- gapLength = newGapEnd - gapStart;
- }
- }
-
- /**
- * Returns the number of elements in this list.
- *
- * @return the number of elements in this list.
- */
- public int size() {
- return elementData.length - gapLength;
- }
-
- /**
- * Tests if this list has no elements.
- *
- * @return true if this list has no elements;
- * false otherwise.
- */
- public boolean isEmpty() {
- return (elementData.length == gapLength);
- }
-
- /**
- * Returns true if this list contains the specified element.
- *
- * @param elem element whose presence in this List is to be tested.
- * @return true
if the specified element is present;
- * false
otherwise.
- */
- public boolean contains(Object elem) {
- return indexOf(elem) >= 0;
- }
-
- /**
- * Searches for the first occurence of the given argument, testing
- * for equality using the equals method.
- *
- * @param elem an object.
- * @return the index of the first occurrence of the argument in this
- * list; returns -1 if the object is not found.
- * @see Object#equals(Object)
- */
- public int indexOf(Object elem) {
- if (elem == null) {
- int i = 0;
- while (i < gapStart) {
- if (elementData[i] == null) {
- return i;
- }
- i++;
- }
- i += gapLength;
- int elementDataLength = elementData.length;
- while (i < elementDataLength) {
- if (elementData[i] == null) {
- return i;
- }
- i++;
- }
-
- } else { // elem not null
- int i = 0;
- while (i < gapStart) {
- if (elem.equals(elementData[i])) {
- return i;
- }
- i++;
- }
- i += gapLength;
- int elementDataLength = elementData.length;
- while (i < elementDataLength) {
- if (elem.equals(elementData[i])) {
- return i;
- }
- i++;
- }
- }
-
- return -1;
- }
-
- /**
- * Returns the index of the last occurrence of the specified object in
- * this list.
- *
- * @param elem the desired element.
- * @return the index of the last occurrence of the specified object in
- * this list; returns -1 if the object is not found.
- */
- public int lastIndexOf(Object elem) {
- if (elem == null) {
- int i = elementData.length - 1;
- int gapEnd = gapStart + gapLength;
- while (i >= gapEnd) {
- if (elementData[i] == null) {
- return i;
- }
- i--;
- }
- i -= gapLength;
- while (i >= 0) {
- if (elementData[i] == null) {
- return i;
- }
- i--;
- }
-
- } else { // elem not null
- int i = elementData.length - 1;
- int gapEnd = gapStart + gapLength;
- while (i >= gapEnd) {
- if (elem.equals(elementData[i])) {
- return i;
- }
- i--;
- }
- i -= gapLength;
- while (i >= 0) {
- if (elem.equals(elementData[i])) {
- return i;
- }
- i--;
- }
- }
-
- return -1;
- }
-
- /**
- * Returns a shallow copy of this GapList instance. (The
- * elements themselves are not copied.)
- *
- * @return a clone of this GapList instance.
- */
- public Object clone() {
- try {
- GapList clonedList = (GapList)super.clone();
- int size = size();
- Object[] clonedElementData = new Object[size];
- copyAllData(clonedElementData);
- clonedList.elementData = clonedElementData;
- // Will retain gapStart - would have to call moved*() otherwise
- clonedList.gapStart = size;
- clonedList.resetModCount();
- return clonedList;
-
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
- }
- }
-
- public void copyItems(int srcStartIndex, int srcEndIndex,
- Object[] dest, int destIndex) {
-
- if (srcStartIndex < 0 || srcEndIndex < srcStartIndex || srcEndIndex > size()) {
- throw new IndexOutOfBoundsException("srcStartIndex=" + srcStartIndex // NOI18N
- + ", srcEndIndex=" + srcEndIndex + ", size()=" + size()); // NOI18N
- }
-
- if (srcEndIndex < gapStart) { // fully below gap
- System.arraycopy(elementData, srcStartIndex,
- dest, destIndex, srcEndIndex - srcStartIndex);
-
- } else { // above gap or spans the gap
- if (srcStartIndex >= gapStart) { // fully above gap
- System.arraycopy(elementData, srcStartIndex + gapLength, dest, destIndex,
- srcEndIndex - srcStartIndex);
-
- } else { // spans gap
- int beforeGap = gapStart - srcStartIndex;
- System.arraycopy(elementData, srcStartIndex, dest, destIndex, beforeGap);
- System.arraycopy(elementData, gapStart + gapLength, dest, destIndex + beforeGap,
- srcEndIndex - srcStartIndex - beforeGap);
- }
- }
- }
-
- /**
- * Returns an array containing all of the elements in this list
- * in the correct order.
- *
- * @return an array containing all of the elements in this list
- * in the correct order.
- */
- public Object[] toArray() {
- int size = size();
- Object[] result = new Object[size];
- copyAllData(result);
- return result;
- }
-
- /**
- * Returns an array containing all of the elements in this list in the
- * correct order; the runtime type of the returned array is that of the
- * specified array. If the list fits in the specified array, it is
- * returned therein. Otherwise, a new array is allocated with the runtime
- * type of the specified array and the size of this list.
- *
- * If the list fits in the specified array with room to spare (i.e., the
- * array has more elements than the list), the element in the array
- * immediately following the end of the collection is set to
- * null. This is useful in determining the length of the list
- * only if the caller knows that the list does not contain any
- * null elements.
- *
- * @param a the array into which the elements of the list are to
- * be stored, if it is big enough; otherwise, a new array of the
- * same runtime type is allocated for this purpose.
- * @return an array containing the elements of the list.
- * @throws ArrayStoreException if the runtime type of a is not a supertype
- * of the runtime type of every element in this list.
- */
- public Object[] toArray(Object a[]) {
- int size = size();
- if (a.length < size) {
- a = (Object[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(), size);
- }
- copyAllData(a);
- if (a.length > size)
- a[size] = null;
-
- return a;
- }
-
- // Positional Access Operations
-
- /**
- * Returns the element at the specified position in this list.
- *
- * @param index index of element to return.
- * @return the element at the specified position in this list.
- * @throws IndexOutOfBoundsException if index is out of range (index
- * < 0 || index >= size()).
- */
- public Object get(int index) {
- // rangeCheck(index) not necessary - would fail with AIOOBE anyway
- return elementData[(index < gapStart) ? index : (index + gapLength)];
- }
-
- /**
- * Replaces the element at the specified position in this list with
- * the specified element.
- *
- * @param index index of element to replace.
- * @param element element to be stored at the specified position.
- * @return the element previously at the specified position.
- * @throws IndexOutOfBoundsException if index out of range
- * (index < 0 || index >= size()).
- */
- public Object set(int index, Object element) {
- // rangeCheck(index) not necessary - would fail with AIOOBE anyway
- if (index >= gapStart) {
- index += gapLength;
- }
- Object oldValue = elementData[index];
- elementData[index] = element;
- return oldValue;
- }
-
- /**
- * Appends the specified element to the end of this list.
- *
- * @param o element to be appended to this list.
- * @return true (as per the general contract of Collection.add).
- */
- public boolean add(Object o) {
- add(size(), o);
- return true;
- }
-
- /**
- * Inserts the specified element at the specified position in this
- * list. Shifts the element currently at that position (if any) and
- * any subsequent elements to the right (adds one to their indices).
- *
- * @param index index at which the specified element is to be inserted.
- * @param element element to be inserted.
- * @throws IndexOutOfBoundsException if index is out of range
- * (index < 0 || index > size()).
- */
- public void add(int index, Object element) {
- int size = size();
- if (index > size || index < 0) {
- throw new IndexOutOfBoundsException(
- "Index: " + index + ", Size: " + size); // NOI18N
- }
-
- ensureCapacity(size + 1); // Increments modCount!!
- moveGap(index);
-
- elementData[gapStart++] = element;
- gapLength--;
- }
-
- /**
- * Appends all of the elements in the specified Collection to the end of
- * this list, in the order that they are returned by the
- * specified Collection's Iterator. The behavior of this operation is
- * undefined if the specified Collection is modified while the operation
- * is in progress. (This implies that the behavior of this call is
- * undefined if the specified Collection is this list, and this
- * list is nonempty.)
- *
- * @param c the elements to be inserted into this list.
- * @return true if this list changed as a result of the call.
- * @throws NullPointerException if the specified collection is null.
- */
- public boolean addAll(Collection c) {
- return addAll(size(), c);
- }
-
- /**
- * Inserts all of the elements in the specified Collection into this
- * list, starting at the specified position. Shifts the element
- * currently at that position (if any) and any subsequent elements to
- * the right (increases their indices). The new elements will appear
- * in the list in the order that they are returned by the
- * specified Collection's iterator.
- *
- * @param index index at which to insert first element
- * from the specified collection.
- * @param c elements to be inserted into this list.
- * @return true if this list changed as a result of the call.
- * @throws IndexOutOfBoundsException if index out of range (index
- * < 0 || index > size()).
- * @throws NullPointerException if the specified Collection is null.
- */
- public boolean addAll(int index, Collection c) {
- return addArray(index, c.toArray());
- }
-
- /*
- * Inserts all elements from the given array into this list, starting
- * at the given index.
- *
- * @param index index at which to insert first element from the array.
- * @param elements array of elements to insert.
- */
- public boolean addArray(int index, Object[] elements) {
- return addArray(index, elements, 0, elements.length);
- }
-
- /**
- * Inserts elements from the given array into this list, starting
- * at the given index.
- *
- * @param index index at which to insert first element.
- * @param elements array of elements from which to insert elements.
- * @param off offset in the elements pointing to first element to copy.
- * @param len number of elements to copy from the elements array.
- */
- public boolean addArray(int index, Object[] elements, int off, int len) {
- int size = size();
- if (index > size || index < 0) {
- throw new IndexOutOfBoundsException(
- "Index: " + index + ", Size: " + size); // NOI18N
- }
-
- ensureCapacity(size + len); // Increments modCount
-
- moveGap(index);
- System.arraycopy(elements, off, elementData, gapStart, len);
- gapStart += len;
- gapLength -= len;
-
- return (len != 0);
- }
-
-
-
- /**
- * Removes all of the elements from this list. The list will
- * be empty after this call returns.
- */
- public void clear() {
- removeRange(0, size());
- }
-
- /**
- * Removes the element at the specified position in this list.
- * Shifts any subsequent elements to the left (subtracts one from their
- * indices).
- *
- * @param index the index of the element to removed.
- * @return the element that was removed from the list.
- * @throws IndexOutOfBoundsException if index out of range (index
- * < 0 || index >= size()).
- */
- public Object remove(int index) {
- int size = size();
- if (index >= size || index < 0) {
- throw new IndexOutOfBoundsException(
- "remove(): Index: " + index + ", Size: " + size); // NOI18N
- }
-
- modCount++;
- moveGap(index + 1); // if previous were adds() - this should be no-op
- Object oldValue = elementData[index];
- removeUpdate(index, elementData, index, index + 1);
- elementData[index] = null;
- gapStart--;
- gapLength++;
-
- return oldValue;
- }
-
- /**
- * Removes elements at the given index.
- *
- * @param index index of the first element to be removed.
- * @param count number of elements to remove.
- */
- public void remove(int index, int count) {
- int toIndex = index + count;
- if (index < 0 || toIndex < index || toIndex > size()) {
- throw new IndexOutOfBoundsException("index=" + index // NOI18N
- + ", count=" + count + ", size()=" + size()); // NOI18N
- }
- removeRange(index, toIndex);
- }
-
- /**
- * Removes from this List all of the elements whose index is between
- * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
- * elements to the left (reduces their index).
- * This call shortens the list by (toIndex - fromIndex) elements.
- * (If toIndex==fromIndex, this operation has no effect.)
- *
- * @param fromIndex index of first element to be removed.
- * @param toIndex index after last element to be removed.
- */
- protected void removeRange(int fromIndex, int toIndex) {
- modCount++;
- if (fromIndex == toIndex) {
- return;
- }
-
- int removeCount = toIndex - fromIndex;
- if (fromIndex >= gapStart) { // completely over gap
- // Move gap to the start of the removed area
- // (this should be the minimum necessary count of elements moved)
- moveGap(fromIndex);
-
- // Allow GC of removed items
- fromIndex += gapLength; // begining of abandoned area
- toIndex += gapLength;
- removeUpdate(fromIndex - gapLength, elementData, fromIndex, toIndex);
- while (fromIndex < toIndex) {
- elementData[fromIndex] = null;
- fromIndex++;
- }
-
- } else { // completely below gap or spans the gap
- if (toIndex <= gapStart) {
- // Move gap to the end of the removed area
- // (this should be the minimum necessary count of elements moved)
- moveGap(toIndex);
- gapStart = fromIndex;
- // Call removeUpdate() for items that will be physically removed soon
- removeUpdate(fromIndex, elementData, fromIndex, toIndex);
-
- } else { // spans gap: gapStart > fromIndex but gapStart - fromIndex < removeCount
- removeUpdate(fromIndex, elementData, fromIndex, gapStart);
- // Allow GC of removed items
- for (int clearIndex = fromIndex; clearIndex < gapStart; clearIndex++) {
- elementData[clearIndex] = null;
- }
-
- fromIndex = gapStart + gapLength; // part above the gap
- gapStart = toIndex - removeCount; // original value of fromIndex
- toIndex += gapLength;
- removeUpdate(gapStart, elementData, fromIndex, toIndex);
- }
-
- // Allow GC of removed items
- while (fromIndex < toIndex) {
- elementData[fromIndex++] = null;
- }
-
- }
-
- gapLength += removeCount;
- }
-
- /**
- * Called prior physical removing of the data from the list.
- *
- * The implementation can possibly update the elements in the removed area.
- *
- * After this method finishes the whole removed area will be
- * null
-ed.
- *
- * @param index index in the list of the first item being removed.
- * @param data array of objects from which the data are being removed.
- * The next two parameters define the indexes at which the elements
- * can be updated.
- *
- * Absolutely no changes should be done outside of
- * <startOff, endOff)
area.
- * @param startOff offset in the data array of the first element that
- * will be removed.
- * @param endOff offset in the data array following the last item that will
- * be removed.
- */
- protected void removeUpdate(int index, Object[] data, int startOff, int endOff) {
- }
-
- /*
- protected void movedAboveGapUpdate(Object[] array, int index, int count) {
- }
-
- protected void movedBelowGapUpdate(Object[] array, int index, int count) {
- }
- */
-
- private void moveGap(int index) {
- if (index == gapStart) {
- return; // do nothing
- }
-
- if (index < gapStart) { // move gap down
- int moveSize = gapStart - index;
- System.arraycopy(elementData, index, elementData,
- gapStart + gapLength - moveSize, moveSize);
- clearEmpty(index, Math.min(moveSize, gapLength));
- gapStart = index;
- // movedAboveGapUpdate(elementData, gapStart + gapLength, moveSize);
-
- } else { // above gap
- int gapEnd = gapStart + gapLength;
- int moveSize = index - gapStart;
- System.arraycopy(elementData, gapEnd, elementData, gapStart, moveSize);
- if (index < gapEnd) {
- clearEmpty(gapEnd, moveSize);
- } else {
- clearEmpty(index, gapLength);
- }
- // movedBelowGapUpdate(elementData, gapStart, moveSize);
- gapStart += moveSize;
- }
- }
-
- private void copyAllData(Object[] toArray) {
- if (gapLength != 0) {
- int gapEnd = gapStart + gapLength;
- System.arraycopy(elementData, 0, toArray, 0, gapStart);
- System.arraycopy(elementData, gapEnd, toArray, gapStart,
- elementData.length - gapEnd);
- } else { // no gap => single copy of everything
- System.arraycopy(elementData, 0, toArray, 0, elementData.length);
- }
- }
-
- private void clearEmpty(int index, int length) {
- while (--length >= 0) {
- elementData[index++] = null; // allow GC
- }
- }
-
- private void resetModCount() {
- modCount = 0;
- }
-
- /**
- * Save the state of the GapList instance to a stream (that
- * is, serialize it).
- *
- * @serialData The length of the array backing the GapList
- * instance is emitted (int), followed by all of its elements
- * (each an Object) in the proper order.
- */
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException{
- // Write out element count, and any hidden stuff
- s.defaultWriteObject();
-
- // Write out array length
- s.writeInt(elementData.length);
-
- // Write out all elements in the proper order.
- int i = 0;
- while (i < gapStart) {
- s.writeObject(elementData[i]);
- i++;
- }
- i += gapLength;
- int elementDataLength = elementData.length;
- while (i < elementDataLength) {
- s.writeObject(elementData[i]);
- i++;
- }
- }
-
- /**
- * Reconstitute the GapList instance from a stream (that is,
- * deserialize it).
- */
- private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- // Read in size, and any hidden stuff
- s.defaultReadObject();
-
- // Read in array length and allocate array
- int arrayLength = s.readInt();
- elementData = new Object[arrayLength];
-
- // Read in all elements in the proper order.
- int i = 0;
- while (i < gapStart) {
- elementData[i] = s.readObject();
- i++;
- }
- i += gapLength;
- int elementDataLength = elementData.length;
- while (i < elementDataLength) {
- elementData[i] = s.readObject();
- i++;
- }
- }
-
- /**
- * Internal consistency check.
- */
- void consistencyCheck() {
- if (gapStart < 0 || gapLength < 0
- || gapStart + gapLength > elementData.length
- ) {
- consistencyError("Inconsistent gap"); // NOI18N
- }
-
- // Check whether the whole gap contains only nulls
- for (int i = gapStart + gapLength - 1; i >= gapStart; i--) {
- if (elementData[i] != null) {
- consistencyError("Non-null value at raw-index i"); // NOI18N
- }
- }
- }
-
- private void consistencyError(String s) {
- throw new IllegalStateException(s + ": " + toStringInternals()); // NOI18N
- }
-
- String toStringInternals() {
- return "elementData.length=" + elementData.length // NOI18N
- + ", gapStart=" + gapStart + ", gapLength=" + gapLength; // NOI18N
- }
-
-}
Index: editor/util/src/org/netbeans/modules/editor/util/PriorityMutex.java
===================================================================
RCS file: editor/util/src/org/netbeans/modules/editor/util/PriorityMutex.java
diff -N editor/util/src/org/netbeans/modules/editor/util/PriorityMutex.java
--- editor/util/src/org/netbeans/modules/editor/util/PriorityMutex.java 29 Jun 2004 09:32:13 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,147 +0,0 @@
-/*
- * Sun Public License Notice
- *
- * The contents of this file are subject to the Sun Public License
- * Version 1.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://www.sun.com/
- *
- * The Original Code is NetBeans. The Initial Developer of the Original
- * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
- * Microsystems, Inc. All Rights Reserved.
- */
-
-package org.netbeans.modules.editor.util;
-
-/**
- * Mutex that allows only one thread to proceed
- * other threads must wait until that one finishes.
- *
- * The thread that "holds" the mutex (has the mutex access granted)
- * may reenter the mutex arbitrary number of times
- * (just increasing a "depth" of the locking).
- *
- * If the priority thread enters waiting on the mutex
- * then it will get serviced first once the current thread
- * leaves the mutex.
- *
- * @author Miloslav Metelka
- * @version 1.00
- */
-
-public class PriorityMutex {
-
- private Thread lockThread;
-
- private int lockDepth;
-
- private Thread waitingPriorityThread;
-
- /**
- * Acquire the ownership of the mutex.
- *
- *
- * The following pattern should always be used: - *
- * mutex.lock(); - * try { - * ... - * } finally { - * mutex.unlock(); - * } - *- */ - public synchronized void lock() { - Thread thread = Thread.currentThread(); - if (thread != lockThread) { // not nested locking - // Will wait if either there is another thread already holding the lock - // or if there is a priority thread waiting but it's not this thread - while (lockThread != null - || (waitingPriorityThread != null && waitingPriorityThread != thread) - ) { - try { - if (waitingPriorityThread == null && isPriorityThread()) { - waitingPriorityThread = thread; - } - - wait(); - - } catch (InterruptedException e) { - waitingPriorityThread = null; - } - } - - lockThread = thread; - - if (thread == waitingPriorityThread) { - waitingPriorityThread = null; // it's now allowed to enter - } - } - - lockDepth++; - } - - /** - * Release the ownership of the mutex. - * - * @see lock() - */ - public synchronized void unlock() { - if (Thread.currentThread() != lockThread) { - throw new IllegalStateException("Not locker"); // NOI18N - } - - if (--lockDepth == 0) { - lockThread = null; - - notifyAll(); // must all to surely notify waitingPriorityThread too - } - } - - /** - * Can be called by the thread - * that acquired the mutex to check whether there - * is a priority thread (such as AWT event-notification thread) - * waiting. - *
null
- * if there is currently no thread holding that acquired this mutex.
- */
- public final synchronized Thread getLockThread() {
- return lockThread;
- }
-
- /**
- * Return true if the current thread that is entering this method
- * is a priority thread
- * and should be allowed to enter as soon as possible.
- *
- *
- * The default implementation assumes that
- * {@link javax.swing.SwingUtilities#isEventDispatchThread()}
- * is a priority thread.
- *
- * @return true if the entering thread is a priority thread.
- */
- protected boolean isPriorityThread() {
- return javax.swing.SwingUtilities.isEventDispatchThread();
- }
-
-}
Index: editor/util/src/org/netbeans/modules/editor/util/element/ElementUtilities.java
===================================================================
RCS file: editor/util/src/org/netbeans/modules/editor/util/element/ElementUtilities.java
diff -N editor/util/src/org/netbeans/modules/editor/util/element/ElementUtilities.java
--- editor/util/src/org/netbeans/modules/editor/util/element/ElementUtilities.java 9 Aug 2004 08:53:57 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,39 +0,0 @@
-/*
- * Sun Public License Notice
- *
- * The contents of this file are subject to the Sun Public License
- * Version 1.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://www.sun.com/
- *
- * The Original Code is NetBeans. The Initial Developer of the Original
- * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
- * Microsystems, Inc. All Rights Reserved.
- */
-
-package org.netbeans.modules.editor.util.element;
-
-import javax.swing.text.Element;
-
-/**
- * Various utility methods related to elements.
- *
- * @author Miloslav Metelka
- * @version 1.00
- */
-
-public final class ElementUtilities {
-
- private ElementUtilities() {
- // No instances
- }
-
- public static void updateOffsetRange(Element[] elements, int[] offsetRange) {
- int elementsLength = elements.length;
- if (elementsLength > 0) {
- offsetRange[0] = Math.min(offsetRange[0], elements[0].getStartOffset());
- offsetRange[1] = Math.max(offsetRange[1], elements[elementsLength - 1].getEndOffset());
- }
- }
-
-}
Index: editor/util/src/org/netbeans/modules/editor/util/element/GapBranchElement.java
===================================================================
RCS file: editor/util/src/org/netbeans/modules/editor/util/element/GapBranchElement.java
diff -N editor/util/src/org/netbeans/modules/editor/util/element/GapBranchElement.java
--- editor/util/src/org/netbeans/modules/editor/util/element/GapBranchElement.java 17 Aug 2004 16:58:37 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,245 +0,0 @@
-/*
- * Sun Public License Notice
- *
- * The contents of this file are subject to the Sun Public License
- * Version 1.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://www.sun.com/
- *
- * The Original Code is NetBeans. The Initial Developer of the Original
- * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
- * Microsystems, Inc. All Rights Reserved.
- */
-
-package org.netbeans.modules.editor.util.element;
-
-import javax.swing.text.Element;
-import javax.swing.event.DocumentEvent;
-import javax.swing.undo.AbstractUndoableEdit;
-import javax.swing.undo.CannotUndoException;
-import javax.swing.undo.CannotRedoException;
-import org.netbeans.modules.editor.util.*;
-
-/**
- * Branch element that uses gap list to maintain its child elements.
- *
- * @author Miloslav Metelka
- * @version 1.00
- */
-
-public abstract class GapBranchElement implements Element {
-
- protected static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0];
-
- private GapList children;
-
- public GapBranchElement() {
- children = new GapList();
- }
-
- public int getElementCount() {
- return children.size();
- }
-
- public Element getElement(int index) {
- return (Element)children.get(index);
- }
-
- public void copyElements(int srcBegin, int srcEnd, Element dst[], int dstBegin) {
- children.copyItems(srcBegin, srcEnd, dst, dstBegin);
- }
-
- /**
- * Gets the child element index closest to the given offset.
- * The offset is specified relative to the beginning of the
- * document. Returns -1
if the
- * Element
is a leaf, otherwise returns
- * the index of the Element
that best represents
- * the given location. Returns 0
if the location
- * is less than the start offset. Returns
- * getElementCount() - 1
if the location is
- * greater than or equal to the end offset.
- *
- *
- * This implementation is in sync with the original
- * Element.getElementIndex()
specification
- * but it differs
- * from AbstractDocument.BranchElement.getElementIndex()
- * which returns 0 in case it does not have any children.
- *
- * This implementation returns -1 in that case because in fact
- * the element act as a leaf element in such case.
- *
- * Nonetheless there should be no difference in functionality
- * if this implementation is used for line elements
- * because there is always at least one line element even
- * for empty doc because of the extra '\n' after the end
- * of the AbstractDocument-based implementations.
- *
- * @param offset the specified offset >= 0
- * @return the element index >= 0
- */
- public int getElementIndex(int offset) {
- int low = 0;
- int high = getElementCount() - 1;
-
- if (high == -1) { // no children => return -1
- return -1;
- }
-
- while (low <= high) {
- int mid = (low + high) / 2;
- int elemStartOffset = getElement(mid).getStartOffset();
-
- if (elemStartOffset < offset) {
- low = mid + 1;
- } else if (elemStartOffset > offset) {
- high = mid - 1;
- } else { // element starts at offset
- return mid;
- }
- }
-
- if (high < 0) { // if offset < getElement(0).getStartOffset()
- high = 0;
- }
- return high;
- }
-
- public boolean isLeaf() {
- return false;
- }
-
- protected void replace(int index, int removeCount, Element[] addedElems) {
- if (removeCount > 0) {
- children.remove(index, removeCount);
- }
- if (addedElems != null) {
- children.addArray(index, addedElems);
- }
- }
-
- /** Get info about DocMarks
. */
- public String toString() {
- return children.toString();
- }
-
- public class Edit extends AbstractUndoableEdit
- implements DocumentEvent.ElementChange {
-
- private int index;
-
- private Element[] childrenAdded;
-
- private Element[] childrenRemoved;
-
- public Edit(int index, Element[] childrenRemoved, Element[] childrenAdded) {
- this.index = index;
- this.childrenRemoved = childrenRemoved;
- this.childrenAdded = childrenAdded;
- }
-
- public Element getElement() {
- return GapBranchElement.this;
- }
-
- public int getIndex() {
- return index;
- }
-
- public Element[] getChildrenRemoved() {
- return childrenRemoved;
- }
-
- public Element[] getChildrenAdded() {
- return childrenAdded;
- }
-
- public void undo() throws CannotUndoException {
- super.undo();
-
- replace(index, childrenAdded.length, childrenRemoved);
-
- // Switch childrenAdded with childrenRemoved
- Element[] tmp = childrenRemoved;
- childrenRemoved = childrenAdded;
- childrenAdded = tmp;
- }
-
- public void redo() throws CannotRedoException {
- super.redo();
-
- // Switch childrenAdded with childrenRemoved
- Element[] tmp = childrenRemoved;
- childrenRemoved = childrenAdded;
- childrenAdded = tmp;
-
- replace(index, childrenRemoved.length, childrenAdded);
- }
-
- }
-
- /**
- * Extension of {@link GapBranchElement}
- * that overrides {@link #getElementIndex(int)}
- * which remembers the last returned element index.
- */
- public abstract class LastIndex {
-
- private int lastReturnedElementIndex;
-
- /**
- * Implementation that remembers the last returned element index
- * and checks the element at the last index when next called.
- *
- * This may improve performance if there are typically many repetitive calls
- * with offset values hitting the last returned element index.
- */
- public int getElementIndex(int offset) {
- int low = 0;
- int high = getElementCount() - 1;
-
- if (high == -1) { // no children => return -1
- return -1;
- }
-
- int lastIndex = lastReturnedElementIndex; // make copy to be thread-safe
- if (lastIndex >= low && lastIndex <= high) {
- Element lastElem = getElement(lastIndex);
- int lastElemStartOffset = lastElem.getStartOffset();
- if (offset >= lastElemStartOffset) {
- int lastElemEndOffset = lastElem.getEndOffset();
- if (offset < lastElemEndOffset) { // hit
- return lastIndex;
- } else { // above
- low = lastIndex + 1;
- }
- } else { // below lastIndex
- high = lastIndex - 1;
- }
- }
-
- while (low <= high) {
- int mid = (low + high) / 2;
- int elemStartOffset = ((Element)children.get(mid)).getStartOffset();
-
- if (elemStartOffset < offset) {
- low = mid + 1;
- } else if (elemStartOffset > offset) {
- high = mid - 1;
- } else { // element starts at offset
- lastReturnedElementIndex = mid;
- return mid;
- }
- }
-
- if (high < 0) {
- high = 0;
- }
- lastReturnedElementIndex = high;
- return high;
- }
-
- }
-
-}
Index: editor/util/test/unit/src/org/netbeans/lib/editor/util/GapListRandomTest.java
===================================================================
RCS file: editor/util/test/unit/src/org/netbeans/lib/editor/util/GapListRandomTest.java
diff -N editor/util/test/unit/src/org/netbeans/lib/editor/util/GapListRandomTest.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ editor/util/test/unit/src/org/netbeans/lib/editor/util/GapListRandomTest.java 21 Mar 2005 17:31:25 -0000
@@ -0,0 +1,187 @@
+/*
+ * Sun Public License Notice
+ *
+ * The contents of this file are subject to the Sun Public License
+ * Version 1.0 (the "License"). You may not use this file except in
+ * compliance with the License. A copy of the License is available at
+ * http://www.sun.com/
+ *
+ * The Original Code is NetBeans. The Initial Developer of the Original
+ * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ */
+
+package org.netbeans.lib.editor.util;
+
+import java.util.ArrayList;
+import java.util.Random;
+import junit.framework.*;
+
+
+/**
+ * Random test of GapList correctness.
+ *
+ * @author mmetelka
+ */
+public class GapListRandomTest extends TestCase {
+
+ private static final boolean debug = false;
+
+ private static final int OP_COUNT_1 = 10000;
+ private static final int ADD_RATIO_1 = 100;
+ private static final int ADD_ALL_RATIO_1 = 10;
+ private static final int ADD_ALL_MAX_COUNT_1 = 10;
+ private static final int REMOVE_RATIO_1 = 100;
+ private static final int REMOVE_RANGE_RATIO_1 = 10;
+ private static final int CLEAR_RATIO_1 = 5;
+ private static final int SET_RATIO_1 = 50;
+
+ private static final int OP_COUNT_2 = 10000;
+ private static final int ADD_RATIO_2 = 50;
+ private static final int ADD_ALL_RATIO_2 = 20;
+ private static final int ADD_ALL_MAX_COUNT_2 = 5;
+ private static final int REMOVE_RATIO_2 = 100;
+ private static final int REMOVE_RANGE_RATIO_2 = 10;
+ private static final int CLEAR_RATIO_2 = 3;
+ private static final int SET_RATIO_2 = 50;
+
+ private ArrayList al;
+
+ private GapList gl;
+
+ public GapListRandomTest(java.lang.String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(GapListRandomTest.class);
+ return suite;
+ }
+
+ protected void setUp() throws java.lang.Exception {
+ }
+
+ protected void tearDown() throws java.lang.Exception {
+ }
+
+ public void test() {
+ testFresh(0);
+ }
+
+ public void testFresh(long seed) {
+ Random random = new Random();
+ if (seed != 0) {
+ System.err.println("TESTING with SEED=" + seed);
+ random.setSeed(seed);
+ }
+
+ gl = new GapList();
+ al = new ArrayList();
+
+
+ testRound(random, OP_COUNT_1, ADD_RATIO_1, ADD_ALL_RATIO_1, ADD_ALL_MAX_COUNT_1,
+ REMOVE_RATIO_1, REMOVE_RANGE_RATIO_1, CLEAR_RATIO_1, SET_RATIO_1);
+ testRound(random, OP_COUNT_2, ADD_RATIO_2, ADD_ALL_RATIO_2, ADD_ALL_MAX_COUNT_2,
+ REMOVE_RATIO_2, REMOVE_RANGE_RATIO_2, CLEAR_RATIO_2, SET_RATIO_2);
+ }
+
+ private void testRound(Random random, int opCount,
+ int addRatio, int addAllRatio, int addAllMaxCount,
+ int removeRatio, int removeRangeRatio, int clearRatio, int setRatio) {
+
+ int ratioSum = addRatio + addAllRatio + removeRatio + removeRangeRatio
+ + clearRatio + setRatio;
+
+ for (int op = 0; op < opCount; op++) {
+ double r = random.nextDouble() * ratioSum;
+
+ if ((r -= addRatio) < 0) {
+ Object o = new Object();
+ int index = (int)(al.size() * random.nextDouble());
+ al.add(index, o);
+ if (debug) {
+ debugOp(op, "add() at index=" + index); // NOI18N
+ }
+ gl.add(index, o);
+
+ } else if ((r -= addAllRatio) < 0) {
+ int count = (int)(random.nextDouble() * addAllMaxCount);
+ ArrayList l = new ArrayList();
+ for (int i = count; i > 0; i--) {
+ l.add(new Object());
+ }
+
+ Object o = new Object();
+ int index = (int)(al.size() * random.nextDouble());
+ al.addAll(index, l);
+ if (debug) {
+ debugOp(op, "addAll() at index=" + index); // NOI18N
+ }
+ gl.addAll(index, l);
+
+ } else if ((r -= removeRatio) < 0) {
+ if (al.size() > 0) { // is anything to remove
+ int index = (int)(al.size() * random.nextDouble());
+ al.remove(index);
+ if (debug) {
+ debugOp(op, "remove() at index=" + index); // NOI18N
+ }
+ gl.remove(index);
+ }
+
+ } else if ((r -= removeRangeRatio) < 0) {
+ if (al.size() > 0) { // is anything to remove
+ int index = (int)(al.size() * random.nextDouble());
+ int length = (int)((al.size() - index + 1) * random.nextDouble());
+ for (int count = length; count > 0; count--) {
+ al.remove(index);
+ }
+ if (debug) {
+ debugOp(op, "remove() at index=" + index + ", length=" + length); // NOI18N
+ }
+ gl.remove(index, length);
+ }
+
+ } else if ((r -= clearRatio) < 0) {
+ al.clear();
+ if (debug) {
+ debugOp(op, "clear()"); // NOI18N
+ }
+ gl.clear();
+
+ } else if ((r -= setRatio) < 0) {
+ if (al.size() > 0) { // is anything to remove
+ int index = (int)(al.size() * random.nextDouble());
+ Object o = new Object();
+ al.set(index, o);
+ if (debug) {
+ debugOp(op, "set() at index=" + index); // NOI18N
+ }
+ gl.set(index, o);
+ }
+ }
+
+ checkConsistency();
+ }
+
+ }
+
+ private void debugOp(int op, String s) {
+ System.err.println("op: " + op + ", " + s + ", " + gl.toStringInternals());
+ }
+
+ private void checkConsistency() {
+ gl.consistencyCheck();
+
+ assertEquals(gl.size(), al.size());
+
+ int size = al.size();
+ for (int i = 0; i < size; i++) {
+ assertTrue("Contents differ at index " + i + ", gl: " + gl.get(i) // NOI18N
+ + ", al:" + al.get(i), // NOI18N
+ (gl.get(i) == al.get(i)));
+ }
+ }
+
+
+}
Index: editor/util/test/unit/src/org/netbeans/modules/editor/util/GapListRandomTest.java
===================================================================
RCS file: editor/util/test/unit/src/org/netbeans/modules/editor/util/GapListRandomTest.java
diff -N editor/util/test/unit/src/org/netbeans/modules/editor/util/GapListRandomTest.java
--- editor/util/test/unit/src/org/netbeans/modules/editor/util/GapListRandomTest.java 18 Aug 2004 17:22:38 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,180 +0,0 @@
-package org.netbeans.modules.editor.util;
-/*
- * GapListTest.java
- * JUnit based test
- *
- * Created on June 26, 2004, 8:37 AM
- */
-
-
-import java.util.ArrayList;
-import java.util.Random;
-import junit.framework.*;
-import junit.framework.*;
-
-/**
- *
- * @author mmetelka
- */
-public class GapListRandomTest extends TestCase {
-
- private static final boolean debug = false;
-
- private static final int OP_COUNT_1 = 10000;
- private static final int ADD_RATIO_1 = 100;
- private static final int ADD_ALL_RATIO_1 = 10;
- private static final int ADD_ALL_MAX_COUNT_1 = 10;
- private static final int REMOVE_RATIO_1 = 100;
- private static final int REMOVE_RANGE_RATIO_1 = 10;
- private static final int CLEAR_RATIO_1 = 5;
- private static final int SET_RATIO_1 = 50;
-
- private static final int OP_COUNT_2 = 10000;
- private static final int ADD_RATIO_2 = 50;
- private static final int ADD_ALL_RATIO_2 = 20;
- private static final int ADD_ALL_MAX_COUNT_2 = 5;
- private static final int REMOVE_RATIO_2 = 100;
- private static final int REMOVE_RANGE_RATIO_2 = 10;
- private static final int CLEAR_RATIO_2 = 3;
- private static final int SET_RATIO_2 = 50;
-
- private ArrayList al;
-
- private GapList gl;
-
- public GapListRandomTest(java.lang.String testName) {
- super(testName);
- }
-
- public static Test suite() {
- TestSuite suite = new TestSuite(GapListRandomTest.class);
- return suite;
- }
-
- protected void setUp() throws java.lang.Exception {
- }
-
- protected void tearDown() throws java.lang.Exception {
- }
-
- public void test() {
- testFresh(0);
- }
-
- public void testFresh(long seed) {
- Random random = new Random();
- if (seed != 0) {
- System.err.println("TESTING with SEED=" + seed);
- random.setSeed(seed);
- }
-
- gl = new GapList();
- al = new ArrayList();
-
-
- testRound(random, OP_COUNT_1, ADD_RATIO_1, ADD_ALL_RATIO_1, ADD_ALL_MAX_COUNT_1,
- REMOVE_RATIO_1, REMOVE_RANGE_RATIO_1, CLEAR_RATIO_1, SET_RATIO_1);
- testRound(random, OP_COUNT_2, ADD_RATIO_2, ADD_ALL_RATIO_2, ADD_ALL_MAX_COUNT_2,
- REMOVE_RATIO_2, REMOVE_RANGE_RATIO_2, CLEAR_RATIO_2, SET_RATIO_2);
- }
-
- private void testRound(Random random, int opCount,
- int addRatio, int addAllRatio, int addAllMaxCount,
- int removeRatio, int removeRangeRatio, int clearRatio, int setRatio) {
-
- int ratioSum = addRatio + addAllRatio + removeRatio + removeRangeRatio
- + clearRatio + setRatio;
-
- for (int op = 0; op < opCount; op++) {
- double r = random.nextDouble() * ratioSum;
-
- if ((r -= addRatio) < 0) {
- Object o = new Object();
- int index = (int)(al.size() * random.nextDouble());
- al.add(index, o);
- if (debug) {
- debugOp(op, "add() at index=" + index); // NOI18N
- }
- gl.add(index, o);
-
- } else if ((r -= addAllRatio) < 0) {
- int count = (int)(random.nextDouble() * addAllMaxCount);
- ArrayList l = new ArrayList();
- for (int i = count; i > 0; i--) {
- l.add(new Object());
- }
-
- Object o = new Object();
- int index = (int)(al.size() * random.nextDouble());
- al.addAll(index, l);
- if (debug) {
- debugOp(op, "addAll() at index=" + index); // NOI18N
- }
- gl.addAll(index, l);
-
- } else if ((r -= removeRatio) < 0) {
- if (al.size() > 0) { // is anything to remove
- int index = (int)(al.size() * random.nextDouble());
- al.remove(index);
- if (debug) {
- debugOp(op, "remove() at index=" + index); // NOI18N
- }
- gl.remove(index);
- }
-
- } else if ((r -= removeRangeRatio) < 0) {
- if (al.size() > 0) { // is anything to remove
- int index = (int)(al.size() * random.nextDouble());
- int length = (int)((al.size() - index + 1) * random.nextDouble());
- for (int count = length; count > 0; count--) {
- al.remove(index);
- }
- if (debug) {
- debugOp(op, "remove() at index=" + index + ", length=" + length); // NOI18N
- }
- gl.remove(index, length);
- }
-
- } else if ((r -= clearRatio) < 0) {
- al.clear();
- if (debug) {
- debugOp(op, "clear()"); // NOI18N
- }
- gl.clear();
-
- } else if ((r -= setRatio) < 0) {
- if (al.size() > 0) { // is anything to remove
- int index = (int)(al.size() * random.nextDouble());
- Object o = new Object();
- al.set(index, o);
- if (debug) {
- debugOp(op, "set() at index=" + index); // NOI18N
- }
- gl.set(index, o);
- }
- }
-
- checkConsistency();
- }
-
- }
-
- private void debugOp(int op, String s) {
- System.err.println("op: " + op + ", " + s + ", " + gl.toStringInternals());
- }
-
- private void checkConsistency() {
- gl.consistencyCheck();
-
- assertEquals(gl.size(), al.size());
-
- int size = al.size();
- for (int i = 0; i < size; i++) {
- assertTrue("Contents differ at index " + i + ", gl: " + gl.get(i) // NOI18N
- + ", al:" + al.get(i), // NOI18N
- (gl.get(i) == al.get(i)));
- }
- }
-
-
-}
Index: ide/golden/public-packages.txt
===================================================================
RCS file: /cvs/ide/golden/public-packages.txt,v
retrieving revision 1.15
diff -u -r1.15 public-packages.txt
--- ide/golden/public-packages.txt 25 Jan 2005 13:04:50 -0000 1.15
+++ ide/golden/public-packages.txt 21 Mar 2005 17:31:26 -0000
@@ -144,6 +144,8 @@
org.netbeans.lib.cvsclient.response
org.netbeans.lib.cvsclient.util
org.netbeans.lib.editor.hyperlink.spi
+org.netbeans.lib.editor.util
+org.netbeans.lib.editor.util.swing
org.netbeans.lib.editor.view
org.netbeans.modules.ant.freeform.spi
org.netbeans.modules.ant.freeform.spi.support
@@ -154,8 +156,6 @@
org.netbeans.modules.editor.java
org.netbeans.modules.editor.options
org.netbeans.modules.editor.plain
-org.netbeans.modules.editor.util
-org.netbeans.modules.editor.util.element
org.netbeans.modules.form
org.netbeans.modules.i18n
org.netbeans.modules.i18n.java