package org.opensha2.eq.fault.surface;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* <b>Title:</b> Container2D<p>
*
* <b>Description:</b> Default Container2DAPI implementation class for a 2D
* grid. This class actually determines the storage mechanism and access to the
* data. This implementation doesn't allow the internal data structure to
* resize. Can design a subclass to do this if needed in the future. <p>
*
* The internal storage is a one dimensional array which is actually accessed by
* two coordinates x and y, i.e. row and column. The two dimensional indices are
* translated to a one dimensional index by the mapping:<p>
*
* index = (the number of columns per row * row) + column. <p>
*
* Note: This data array stored Objects so the actually data that you store can
* be any Java class. This container is flexible to hold any type of data at
* each "grid" point. <p>
*
* @author Steven W. Rock
*/
class Container2DImpl<T> implements Container2D<T> {
/** Array of data elements - 2D flattened into 1D Array */
private Object[] data;
/** The number of rows in this two dimensional matrix. */
private int numRows = 0;
/** The number of columns in this two dimensional matrix. */
private int numCols = 0;
/** The number of rows times the number of columns. */
private long size = 0L;
/**
* Name assigned to an instance of this container. Can be used to display in a
* GUI, or used as a key in a Java Hashtable.
*/
private String name;
/**
* No Argument Constructor for the Container2D object. Set's a default row and
* column size to = 100.
*/
public Container2DImpl() {
this(100, 100);
}
/**
* Constructs a new <code>Container2D</code> with the supplied dimensions.
*
* @param numRows number of rows
* @param numCols number of columns
* @exception IllegalArgumentException if <code>numRows</code> or
* <code>numCols</code> are less than 1, or if <code>(numRows *
* numCols)</code> exceeds the allowable 32-bit address space
* [2147483647].
*/
public Container2DImpl(int numRows, int numCols) {
checkArgument(numRows > 0, "Number of rows must be greater than 0");
checkArgument(numCols > 0, "Number of columns must be greater than 0");
checkArgument((((long) numRows * (long) numCols) < 2147483647L),
"Container size exceeds allowable 32-bit address space");
this.numRows = numRows;
this.numCols = numCols;
size = (long) numRows * (long) numCols;
data = new Object[numRows * numCols];
}
/** Sets the name of this container */
@Override
public void setName(String name) {
this.name = name;
}
/** Gets the name of this container */
@Override
public String name() {
return name;
}
/**
* Places a Java object into one cell in this two dimensional matrix specified
* by the row and column indices.
*
* @param row The x coordinate of the cell.
* @param column The y coordinate of the cell.
* @param obj The Java object to place in the cell.
* @exception ArrayIndexOutOfBoundsException Thrown if the row and column are
* beyond the two dimensional matrix range.
*/
@Override
public void set(int row, int column, T obj) throws ArrayIndexOutOfBoundsException {
checkBounds(row, column);
data[row * numCols + column] = obj;
}
/**
* Sets the number of Rows and Cols of the 2D container object.
* @param numRows int number of rows
* @param numCols int number of cols
*/
protected void setNumRowsAndNumCols(int numRows, int numCols) {
this.numCols = numCols;
this.numRows = numRows;
size = (long) numRows * (long) numCols;
data = new Object[numRows * numCols];
}
/**
* Returns the number of rows int this two dimensional container.
*
* @return Number of rows.
*/
@Override
public int getNumRows() {
return numRows;
}
/**
* Returns the number of columns in this two dimensional container.
*
* @return Get number of columns.
*/
@Override
public int getNumCols() {
return numCols;
}
/**
* Returns the object stored in this two dimensional cell.
*
* @param row The x coordinate of the cell.
* @param column The y coordinate of the cell.
*/
@Override
@SuppressWarnings("unchecked")
public T get(int row, int column) {
checkBounds(row, column);
return (T) data[row * numCols + column];
}
/**
* Returns an ordered list iterator over all columns associated with one row.
* This returns all the objects in that row. The results are returned from
* lowest index to highest along the interating row.
*
* @param row The x coordinate of the cell.
* @return The columnIterator value
* @exception ArrayIndexOutOfBoundsException Thrown if the row is beyond the
* two dimensional matrix range.
*/
@Override
public ListIterator<T> getColumnIterator(int row) throws ArrayIndexOutOfBoundsException {
if (row >= numRows) {
throw new ArrayIndexOutOfBoundsException("colIt: Row cannot be greater than max index");
}
ColumnIterator it = new ColumnIterator(row);
return it;
}
/**
* Returns an ordered list iterator over all rows associated with one column.
* This returns all the objects in that column. The results are returned from
* lowest index to highest along the interating column.
*
* @param column The y coordinate of the cell.
* @return The rowIterator value
* @exception ArrayIndexOutOfBoundsException Thrown if the column is beyond
* the two dimensional matrix range.
*/
@Override
public ListIterator<T> getRowIterator(int column) throws ArrayIndexOutOfBoundsException {
if (column >= numCols) {
throw new ArrayIndexOutOfBoundsException(
"rowIt Column cannot be greater than max index");
}
RowIterator it = new RowIterator(column);
return it;
}
/**
* This returns an iterator of all the Java objects stored in this two
* dimensional matrix iterating over all rows within a column and then moving
* to the next column until iteration has been done over all rows and all
* columns.
*
* @return The allByColumnsIterator value
*/
@Override
public ListIterator<T> getAllByColumnsIterator() {
AllByColumnsIterator it = new AllByColumnsIterator();
return it;
}
/**
* This returns an iterator of all the Java objects stored in this two
* dimensional matrix iterating over all columns within a rows and then moving
* to the next column until iteration has been done over all columns and all
* rows.
*
* @return The allByRowsIterator value
*/
@Override
public ListIterator<T> getAllByRowsIterator() {
AllByRowsIterator it = new AllByRowsIterator();
return it;
}
/**
* Checks that the specified row and column are valid indices into the 2D
* array. Internal helper function used only by this class.
*
* @param row check row value less that max row index
* @param column check col value less that max col index
* @exception ArrayIndexOutOfBoundsException Thrown if row or column < 0 or >
* max row or max col.
*/
protected void checkBounds(int row, int column)
throws ArrayIndexOutOfBoundsException {
if (row < 0) {
throw new ArrayIndexOutOfBoundsException("Container2D Row cannot be less than zero");
}
if (column < 0) {
throw new ArrayIndexOutOfBoundsException("Container2D Column cannot be less than zero");
}
if (row >= numRows) {
throw new ArrayIndexOutOfBoundsException(
"Container2D Row cannot be greater than max index: " + numRows);
}
if (column >= numCols) {
throw new ArrayIndexOutOfBoundsException(
"Container2D Column cannot be greater than max index: " + numCols);
}
}
/**
* Removes all object reference stored in this container and resets all grid
* metics back to 0. Doesn't delete the actual objects, only removes the
* pointer references stored at each grid cell location.
*/
@Override
public void clear() {
data = null;
numRows = 0;
numCols = 0;
size = 0L;
}
/**
* Removes the object's reference stored in the grid cell. Doesn't delete the
* actual object, only removes the pointer reference. This class losses any
* reference to the data object, but that object may still be referenced in
* some other class.
*
* @param row The x coordinate of the cell.
* @param column The y coordinate of the cell.
*/
// public void delete( int row, int column ) {
//
// String S = C + ": delete(): ";
// checkBounds( row, column, S );
// data[row * numCols + column] = null;
//
// }
/**
* check if this grid cell has a java object stored in it. Returns false if
* this data point is null.
*
* @param row The x coordinate of the cell.
* @param column The y coordinate of the cell.
* @return True if an object has been set in this cell.
*/
@Override
public boolean exist(int row, int column) {
checkBounds(row, column);
if (get(row, column) == null) {
return false;
} else {
return true;
}
}
/**
* returns the number of cells in this two dimensional matrix, i.e. numwRows *
* numCols.
*
* @return The number of cells.
*/
@Override
public long size() {
return size;
}
// /**
// * The most generic iterator that returns all Java stored in this two
// * dimensional matrix with no guarantee of ordering either by rows or by
// * columns. Internally this function will probably just call get
// * allByRowsIterator
// *
// * @return Description of the Return Value
// */
// public ListIterator<T> listIterator() {
// AllByRowsIterator it = new AllByRowsIterator();
// return it;
// }
/**
* Converts our internal data structure to the Java 2 dimensional array.
* Helper translation function.
* @return 2D Object array - Object[][]
*/
public Object[][] toJava2D() {
Object[][] d = new Object[numRows][numCols];
for (int j = 0; j < numRows; j++) {
for (int i = 0; i < numCols; i++) {
d[i][j] = get(i, j);
}
}
return d;
}
// /**
// * The main program for the Container2D class. Simple tester application
// * that verifies the container class is working as expected. Not a unit
// * test case harness, just simple and quick user verification by eye,
// *
// * @param args The command line arguments
// */
// public static void main( String[] args ) {
//
// String S = C + ": Main(): ";
// System.out.println( S + "Starting" );
//
// int xsize = 5;
// int ysize = 10;
//
// Container2DImpl<String> con = new Container2DImpl<String>( xsize, ysize
// );
// for ( int x = 0; x < xsize; x++ ) {
// for ( int y = 0; y < ysize; y++ ) {
// con.set( x, y, "" + x + ", " + y );
// }
// }
//
// System.out.println( S + "(1,1) = " + con.get( 1, 1 ) );
//
// System.out.println( S );
// System.out.println( S );
// System.out.println( S + "getRowIterator" );
//
// ListIterator<String> it = con.getRowIterator( 2 );
// while ( it.hasNext() ) {
//
// String obj = it.next();
// System.out.println( S + obj.toString() );
// }
//
// System.out.println( S );
// System.out.println( S );
// System.out.println( S + "getColumnIterator" );
//
// it = con.getColumnIterator( 2 );
// while ( it.hasNext() ) {
//
// String obj = it.next();
// System.out.println( S + obj.toString() );
//
// }
//
// System.out.println( S );
// System.out.println( S );
// System.out.println( S + "getAllByColumnsIterator" );
//
// it = con.getAllByColumnsIterator();
// while ( it.hasNext() ) {
//
// String obj = it.next();
// System.out.println( S + obj.toString() );
//
// }
//
// System.out.println( S );
// System.out.println( S );
// System.out.println( S + "getAllByRowsIterator" );
//
// it = con.getAllByRowsIterator();
// while ( it.hasNext() ) {
//
// String obj = it.next();
// System.out.println( S + obj.toString() );
//
// }
//
// System.out.println( S );
// System.out.println( S );
// System.out.println( S + "List Iterator" );
//
// it = con.listIterator();
// while ( it.hasNext() ) {
//
// String obj = it.next();
// System.out.println( S + obj.toString() );
// }
//
// System.out.println( S + "Ending" );
//
// }
/**
* <b>Title:</b> Container2DListIterator<p>
*
* <b>Description:</b> Base abstract class for all iterators. Stores the
* indexes, etc, and implements nextIndex() and hasNext(). All unsupported
* methods throws Exceptions. <p>
*
* This is how iterators should be handled, i.e. the class should be an inner
* class so that the outside world only ever sees a ListIterator.<p>
*
* The iterator shouldn't be in a seperate class file because it needs
* intimate knowledge to the data structure (in this case a java array) which
* is usually hidden to the outside world. By making it an inner class, the
* iterator has full access to the private variables of the data class.<p>
*
* This implementation allows read only access to the collection as iterating
* over it, in other words, several write functions are not implemented ere,
* just throws UnsupportedException.<p>
*
* @author Steven W. Rock
* @created February 25, 2002
* @version 1.0
*/
abstract class Container2DListIterator implements ListIterator<T> {
/** Current index into the collection */
int cursor = 0;
/** */
int lastRet = -1;
/** */
int lastIndex = 0;
/**
* No arg constructgor - returns full column to iterate over, pinned to one
* row
*/
public Container2DListIterator() {}
/**
* Not implemented, but part of the ListIterator API
*
* @param obj New value at current iteration index
* @exception UnsupportedOperationException Funciton not currently
* implemented .
*/
@Override
public void set(Object obj) throws UnsupportedOperationException {
throw new UnsupportedOperationException("set(Object obj) Not implemented.");
}
/**
* Returns true if there are more elements in this container, else returns
* false.
*/
@Override
public boolean hasNext() {
return cursor != lastIndex;
}
/** Returns the index value of the next iteration. */
@Override
public int nextIndex() {
return cursor;
}
/**
* Returns the next object from this collection container.
*
* @return The object stored at the next index
* @exception NoSuchElementException No more elements available, at end of
* list.
*/
@Override
public abstract T next() throws NoSuchElementException;
/**
* Rolls back the iterator to the previous index, returning the previous
* object stored at that index.
*
* @return The object stored at the previous index
* @exception UnsupportedOperationException Function currently not
* implemented.
*/
@Override
public T previous() throws UnsupportedOperationException {
throw new UnsupportedOperationException("hasPrevious() Not implemented.");
}
/**
* Returns the index value of the next iteration.
*
* @exception UnsupportedOperationException Function currently not
* implemented.
*/
@Override
public int previousIndex() throws UnsupportedOperationException {
throw new UnsupportedOperationException("hasPrevious() Not implemented.");
}
/**
* Checks if not at begining of iteration.
*
* @return True if previous, false otherwise.
* @exception UnsupportedOperationException Function currently not
* implemented.
*/
@Override
public boolean hasPrevious() throws UnsupportedOperationException {
throw new UnsupportedOperationException("hasPrevious() Not implemented.");
}
/**
* Allows updating object in the container as iteration over elements
*
* @param obj New value at iteration point.
* @exception UnsupportedOperationException Function currently not
* implemented.
*/
@Override
public void add(Object obj) throws UnsupportedOperationException {
throw new UnsupportedOperationException("add(Object obj) Not implemented.");
}
/**
* Deletes the next object in the iteration
*
* @exception UnsupportedOperationException Function currently not
* implemented.
*/
@Override
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException("remove() Not implemented.");
}
}
/**
* <b>Title:</b> ColumnIterator<p> <b>Description:</b> Returns all column
* points for one row<p>
*
* @author Steven W. Rock
* @created February 25, 2002
* @version 1.0
*/
class ColumnIterator extends Container2DListIterator {
/**
* Description of the Field
*/
int pinnedRow;
/**
* returns full column to iterate over, pinned to one row
*
* @param row Description of the Parameter
*/
public ColumnIterator(int row) {
super();
this.pinnedRow = row;
lastIndex = numCols;
}
/**
* Description of the Method
*
* @return Description of the Return Value
* @exception NoSuchElementException Description of the Exception
*/
@Override
@SuppressWarnings("unchecked")
public T next() throws NoSuchElementException {
try {
T object = (T) data[pinnedRow * numCols + cursor];
lastRet = cursor++;
return object;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException(
"You have iterated past the last element." + e.toString());
}
}
}
/**
* <b>Title:</b> RowIterator<> <b>Description:</b> Returns all column points
* for one row<p>
*
*
* @author Steven W. Rock
* @created February 25, 2002
* @version 1.0
*/
class RowIterator extends Container2DListIterator {
/**
* Description of the Field
*/
int pinnedColumn;
/**
* returns full column to iterate over, pinned to one row
*
* @param column Description of the Parameter
*/
public RowIterator(int column) {
super();
this.pinnedColumn = column;
lastIndex = numRows;
}
/**
* Description of the Method
*
* @return Description of the Return Value
* @exception NoSuchElementException Description of the Exception
*/
@Override
@SuppressWarnings("unchecked")
public T next() throws NoSuchElementException {
try {
// T object = (T)data[cursor * numCols + pinnedColumn];
T object = get(cursor, pinnedColumn);
lastRet = cursor++;
return object;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException(
"You have iterated past the last element." + e.toString());
}
}
}
/**
* <b>Title:</b> AllByColumnsIterator<p> <b>Description:</b> Returns all rows
* for a column, then moves to the next column<p>
*
* @author Steven W. Rock
* @created February 25, 2002
* @version 1.0
*/
class AllByColumnsIterator extends Container2DListIterator {
/**
* Description of the Field
*/
int currentColumn = 0;
/**
* Description of the Field
*/
int currentRow = 0;
/**
* Constructor for the AllByColumnsIterator object
*/
public AllByColumnsIterator() {
super();
lastIndex = numCols * numRows;
}
/**
* Description of the Method
*
* @return Description of the Return Value
* @exception NoSuchElementException Description of the Exception
*/
@Override
@SuppressWarnings("unchecked")
public T next() throws NoSuchElementException {
try {
// T object = (T)data[currentRow * numCols + currentColumn];
T object = get(currentRow, currentColumn);
currentRow++;
if (currentRow == numRows) {
currentRow = 0;
currentColumn++;
}
lastRet = cursor++;
return object;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException(
"You have iterated past the last element. " + e.toString());
}
}
}
/**
* <b>Title:</b> AllByRowsIterator<p> <b>Description:</b> Returns all columns
* for a row, then moves to the next row<p>
*
* @author Steven W. Rock
* @created February 25, 2002
* @version 1.0
*/
class AllByRowsIterator extends Container2DListIterator {
/**
* Constructor for the AllByRowsIterator object
*/
public AllByRowsIterator() {
super();
lastIndex = numCols * numRows;
}
/**
* Description of the Method
*
* @return Description of the Return Value
* @exception NoSuchElementException Description of the Exception
*/
@Override
@SuppressWarnings("unchecked")
public T next() throws NoSuchElementException {
try {
int row = cursor / numCols;
int col = cursor % numCols;
// T object = (T)data[cursor];
// System.out.println("cursor="+cursor+",
// row="+row+"/"+numRows+", col="+col+"/"+numCols);
T object = get(row, col);
lastRet = cursor++;
return object;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException(
"You have iterated past the last element. " + e.toString());
}
}
}
private final static char TAB = '\t';
/** Prints out each location and fault information for debugging */
@Override
public String toString() {
StringBuffer b = new StringBuffer();
b.append('\n');
int i = 0, j, counter = 0;
while (i < numRows) {
j = 0;
while (j < numCols) {
b.append("" + i + TAB + j + TAB);
Object obj = this.get(i, j);
if (obj != null) {
b.append(obj.toString());
counter++;
} else {
b.append("NULL");
}
b.append('\n');
j++;
}
i++;
}
b.append("\nNumber of Rows = " + numRows + '\n');
b.append("Number of Columns = " + numCols + '\n');
b.append("Size = " + size + '\n');
b.append("Number of non-null objects = " + counter + '\n');
return b.toString();
}
@Override
public Iterator<T> iterator() {
// return listIterator();
return new AllByRowsIterator();
}
}