/*******************************************************************************
*
* Copyright 2010 Alexandru Craciun, and individual contributors as indicated
* by the @authors tag.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
******************************************************************************/
package org.netxilia.api.utils;
import java.util.ArrayList;
import java.util.List;
public class MatrixBuilder<E> {
private List<List<E>> elements;
private final IMatrixElementCreator<E> elementCreator;
public MatrixBuilder(E nullElement) {
this(sameElement(nullElement));
}
public MatrixBuilder(IMatrixElementCreator<E> elementCreator) {
if (elementCreator == null) {
throw new NullPointerException();
}
elements = new ArrayList<List<E>>();
this.elementCreator = elementCreator;
}
public MatrixBuilder(Matrix<E> matrix, final E nullElement) {
this(matrix, sameElement(nullElement));
}
public MatrixBuilder(Matrix<E> matrix, IMatrixElementCreator<E> elementCreator) {
elements = new ArrayList<List<E>>(matrix.getRowCount());
for (List<E> row : matrix.getRows()) {
elements.add(new ArrayList<E>(row));
}
this.elementCreator = elementCreator;
}
private static <T> IMatrixElementCreator<T> sameElement(final T nullElement) {
return new IMatrixElementCreator<T>() {
@Override
public T newElement(int row, int column) {
return nullElement;
}
};
}
public int getColumnCount() {
if (elements.size() == 0) {
return 0;
}
return elements.get(0).size();
}
private List<E> emptyRow(int row) {
return CollectionUtils.atLeastSize(new ArrayList<E>(), getColumnCount(), new CellCreator(elementCreator, row));
}
private void elementsWithSize(int rowCount, int columnCount) {
if (rowCount <= elements.size() && columnCount <= getColumnCount()) {
return;
}
CellCreator cellCreator = new CellCreator(elementCreator, 0);
if (rowCount > elements.size()) {
RowCreator rowCreator = new RowCreator(cellCreator, Math.max(columnCount, getColumnCount()));
elements = CollectionUtils.atLeastSize(elements, rowCount, rowCreator);
}
if (columnCount > getColumnCount()) {
for (int i = 0; i < elements.size(); ++i) {
List<E> row = elements.get(i);
if (cellCreator != null) {
cellCreator.setRow(i);
}
elements.set(i, CollectionUtils.atLeastSize(row, columnCount, cellCreator));
}
}
}
public MatrixBuilder<E> set(int r, int c, E element) {
elementsWithSize(r + 1, c + 1);
elements.get(r).set(c, element);
return this;
}
public MatrixBuilder<E> removeColumn(int columnIndex) {
for (List<E> row : elements) {
row.remove(columnIndex);
}
return this;
}
public MatrixBuilder<E> removeRow(int rowIndex) {
elements.remove(rowIndex);
return this;
}
public MatrixBuilder<E> insertRow(int index) {
elements.add(index, emptyRow(index));
return this;
}
public MatrixBuilder<E> setSize(int rowCount, int columnCount) {
elementsWithSize(rowCount, columnCount);
return this;
}
public Matrix<E> build() {
return new Matrix<E>(elements);
}
private class CellCreator implements IListElementCreator<E> {
private final IMatrixElementCreator<E> elementCreator;
private int row;
public CellCreator(IMatrixElementCreator<E> elementCreator, int row) {
this.elementCreator = elementCreator;
this.row = row;
}
public void setRow(int row) {
this.row = row;
}
public E newElement(int column) {
return elementCreator.newElement(row, column);
}
}
private class RowCreator implements IListElementCreator<List<E>> {
private final CellCreator cellCreator;
private final int columnCount;
public RowCreator(CellCreator cellCreator, int columnCount) {
this.cellCreator = cellCreator;
this.columnCount = columnCount;
}
@Override
public List<E> newElement(int row) {
if (cellCreator != null) {
cellCreator.setRow(row);
}
List<E> newRow = CollectionUtils.atLeastSize(new ArrayList<E>(), columnCount, cellCreator);
return newRow;
}
}
}