ca.odell.glazedlists.impl.adt.barcode2.FourColorTreeIterator Maven / Gradle / Ivy
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.impl.adt.barcode2;
import java.util.NoSuchElementException;
/*
# some M4 Macros that make it easy to use m4 with Java
M4 Macros
# define a function NODE_WIDTH(boolean) to get the node's size for this color
# define a function NODE_SIZE(node, colors) to no node.nodeSize()
# define a function to refresh counts
# multiple values
*/
/*[ BEGIN_M4_JAVA ]*/
/**
* Iterate through a {@link FourColorTree}, one element at a time.
*
* We should consider adding the following enhancements to this class:
*
writing methods, such as set()
and remove()
.
* a default color, specified at construction time, that shall always be
* used as the implicit parameter to overloaded versions of {@link #hasNext}
* and {@link #next}.
*
* @author Jesse Wilson
*/
public class FourColorTreeIterator < T0> {
int count1;
int count2;
int count4;
int count8;
private FourColorTree < T0> tree;
private FourColorNode < T0> node;
private int index;
public FourColorTreeIterator/**/(FourColorTree < T0> tree) {
this(tree, 0, (byte)0);
}
/**
* Create an iterator starting at the specified index.
*
* @param tree the tree to iterate
* @param nextIndex the index to be returned after calling {@link #next next()}.
* @param nextIndexColors the colors to interpret nextIndex in terms of
*/
public FourColorTreeIterator/**/(FourColorTree < T0> tree, int nextIndex, byte nextIndexColors) {
this.tree = tree;
// if the start is, we need to find the node in the tree
if(nextIndex != 0) {
int currentIndex = nextIndex - 1;
this.node = ( FourColorNode < T0> )tree.get(currentIndex , nextIndexColors );
// find the counts
count1 = tree.convertIndexColor(currentIndex, nextIndexColors, (byte)1) + (node.color == 1 ? 0 : 1);
count2 = tree.convertIndexColor(currentIndex, nextIndexColors, (byte)2) + (node.color == 2 ? 0 : 1);
count4 = tree.convertIndexColor(currentIndex, nextIndexColors, (byte)4) + (node.color == 4 ? 0 : 1);
count8 = tree.convertIndexColor(currentIndex, nextIndexColors, (byte)8) + (node.color == 8 ? 0 : 1);
// find out the index in the node
if(node.color == 1) this.index = count1 - tree.indexOfNode(this.node, (byte)1);
if(node.color == 2) this.index = count2 - tree.indexOfNode(this.node, (byte)2);
if(node.color == 4) this.index = count4 - tree.indexOfNode(this.node, (byte)4);
if(node.color == 8) this.index = count8 - tree.indexOfNode(this.node, (byte)8);
// just start before the beginning of the tree
} else {
this.node = null;
this.index = 0;
}
}
/**
* Create a {@link FourColorTreeIterator} exactly the same as this one.
* The iterators will be backed by the same tree but maintain
* separate cursors into the tree.
*/
public FourColorTreeIterator < T0> copy() {
FourColorTreeIterator < T0> result = new FourColorTreeIterator < T0> (tree);
result.count1 = this.count1;
result.count2 = this.count2;
result.count4 = this.count4;
result.count8 = this.count8;
result.node = node;
result.index = index;
return result;
}
/**
* @return true
if there's an element of the specified color in
* this tree following the current element.
*/
public boolean hasNext( byte colors ) {
if(node == null) {
return tree.size( colors ) > 0;
} else if( (colors & node.color) != 0 ) {
return index( colors ) < tree.size( colors ) - 1;
} else {
return index( colors ) < tree.size( colors );
}
}
/**
* @return true
if there's a node of the specified color in this
* tree following the current node.
*/
public boolean hasNextNode( byte colors ) {
if(node == null) {
return tree.size( colors ) > 0;
} else {
return nodeEndIndex( colors ) < tree.size( colors );
}
}
/**
* Step to the next element.
*/
public void next( byte colors ) {
if(!hasNext( colors )) {
throw new NoSuchElementException();
}
// start at the first node in the tree
if(node == null) {
node = tree.firstNode();
index = 0;
if((node.color & colors) != 0) return;
// increment within the current node
} else if( (node.color & colors) != 0 && index < node.size - 1) {
if(node.color == 1) count1++;
if(node.color == 2) count2++;
if(node.color == 4) count4++;
if(node.color == 8) count8++;
index++;
return;
}
// scan through the nodes, looking for the first one of the right color
while(true) {
if(node.color == 1) count1 += node.size - index;
if(node.color == 2) count2 += node.size - index;
if(node.color == 4) count4 += node.size - index;
if(node.color == 8) count8 += node.size - index;
node = FourColorTree.next(node);
index = 0;
// we've found a node that meet our requirements, so return
if((node.color & colors) != 0) break;
}
}
/**
* Step to the next node.
*/
public void nextNode( byte colors ) {
if(!hasNextNode( colors )) {
throw new NoSuchElementException();
}
// start at the first node in the tree
if(node == null) {
node = tree.firstNode();
index = 0;
if((node.color & colors) != 0) return;
}
// scan through the nodes, looking for the first one of the right color
while(true) {
if(node.color == 1) count1 += node.size - index;
if(node.color == 2) count2 += node.size - index;
if(node.color == 4) count4 += node.size - index;
if(node.color == 8) count8 += node.size - index;
node = FourColorTree.next(node);
index = 0;
// we've found a node that meet our requirements, so return
if((node.color & colors) != 0) break;
}
}
/**
* Get the size of the current node, or 0 if it's color doesn't match those
* specified.
*/
public int nodeSize( byte colors ) {
if( (node.color & colors) != 0 ) {
return node.size ;
} else {
return 0;
}
}
/**
* The color of the current element.
*/
public byte color() {
if(node == null) throw new IllegalStateException();
return node.color;
}
/**
* Expected values for index should be in the range ( 0, size() - 1 )
*/
public int index( byte colors ) {
if(node == null) throw new NoSuchElementException();
// total the values of the specified array for the specified colors.
int result = 0;
if((colors & 1) != 0) result += count1;
if((colors & 2) != 0) result += count2;
if((colors & 4) != 0) result += count4;
if((colors & 8) != 0) result += count8;
return result;
}
/**
* Get the index of the current node's start.
*/
public int nodeStartIndex( byte colors ) {
if(node == null) throw new NoSuchElementException();
// the count of all nodes prior to this one
int result = 0;
// this should merely be the sum of each count
if((colors & 1) != 0) result += count1;
if((colors & 2) != 0) result += count2;
if((colors & 4) != 0) result += count4;
if((colors & 8) != 0) result += count8;
// subtract the count of anything in the current node which we may
// have included inadvertently
if( (node.color & colors) != 0 ) {
result -= index;
}
return result;
}
/**
* Get the index of the node immediately following the current. Expected
* values are in the range ( 1, size() )
*/
public int nodeEndIndex( byte colors ) {
if(node == null) throw new NoSuchElementException();
// the count of all nodes previous
return nodeStartIndex( colors )
+ nodeSize( colors );
}
public T0 value() {
if(node == null) throw new IllegalStateException();
return node.get();
}
public Element node() {
if(node == null) throw new IllegalStateException();
return node;
}
}
/*[ END_M4_JAVA ]*/