/*******************************************************************************
*
* 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.spi.impl.storage.memory;
import java.util.Collection;
import java.util.List;
import org.netxilia.api.exception.NotFoundException;
import org.netxilia.api.exception.StorageException;
import org.netxilia.api.model.CellData;
import org.netxilia.api.model.CellDataWithProperties;
import org.netxilia.api.model.ColumnData;
import org.netxilia.api.model.ColumnData.Property;
import org.netxilia.api.model.RowData;
import org.netxilia.api.model.SheetData;
import org.netxilia.api.model.SheetDimensions;
import org.netxilia.api.reference.AreaReference;
import org.netxilia.api.reference.CellReference;
import org.netxilia.api.reference.IReferenceTransformer;
import org.netxilia.api.reference.Range;
import org.netxilia.api.reference.ReferenceTransformers;
import org.netxilia.api.utils.Matrix;
import org.netxilia.api.utils.MatrixBuilder;
import org.netxilia.spi.storage.ISheetStorageService;
public class InMemorySheetStorageServiceImpl implements ISheetStorageService {
private final CompleteSheet sheet;
public InMemorySheetStorageServiceImpl(CompleteSheet sheet) {
this.sheet = sheet;
}
public CompleteSheet getSheet() {
return sheet;
}
@Override
public synchronized void deleteRow(int row) throws StorageException, NotFoundException {
if (row < sheet.getRows().size()) {
sheet.getRows().remove(row);
// REMOVE also cells
sheet.setCells(sheet.getCellsBuilder().removeRow(row).build());
applyTransformer(sheet, ReferenceTransformers.deleteRow(row));
}
}
@Override
public synchronized List<RowData> loadRows(Range rows) throws StorageException, NotFoundException {
int count = sheet.getRows().size();
return sheet.getRows().subList(Math.min(count, rows.getMin()), Math.min(rows.getMax(), count));
}
@Override
public synchronized void saveRow(RowData row, Collection<RowData.Property> properties) throws StorageException,
NotFoundException {
List<RowData> rows = sheet.getRows();
minRows(rows, row.getIndex() + 1);
rows.set(row.getIndex(), row);
}
@Override
public synchronized void insertRow(RowData row, Collection<RowData.Property> properties) throws StorageException,
NotFoundException {
if (row.getIndex() < sheet.getRows().size()) {
sheet.getRows().add(row.getIndex(), row);
sheet.setCells(sheet.getCellsBuilder().insertRow(row.getIndex()).build());
applyTransformer(sheet, ReferenceTransformers.insertRow(row.getIndex()));
} else {
minRows(sheet.getRows(), row.getIndex() + 1);
sheet.getRows().set(row.getIndex(), row);
}
}
@Override
public synchronized Matrix<CellData> loadCells(AreaReference area) throws StorageException, NotFoundException {
Matrix<CellData> cells = sheet.getCells();
return cells.subMatrix(
Math.min(area.getFirstRowIndex(), cells.getRowCount()),//
Math.min(area.getFirstColumnIndex(), cells.getColumnCount()),
Math.min(area.getLastRowIndex() + 1, cells.getRowCount()),
Math.min(area.getLastColumnIndex() + 1, cells.getColumnCount()));
}
@Override
public synchronized List<ColumnData> loadColumns(Range columns) throws StorageException, NotFoundException {
int count = sheet.getColumns().size();
return sheet.getColumns().subList(Math.min(count, columns.getMin()), Math.min(columns.getMax(), count));
}
@Override
public synchronized void saveCells(Collection<CellDataWithProperties> cells) throws StorageException,
NotFoundException {
for (CellDataWithProperties saveCell : cells) {
saveCell(saveCell.getCellData(), saveCell.getProperties());
}
}
public synchronized void saveCell(CellData cell, Collection<CellData.Property> properties) throws StorageException,
NotFoundException {
sheet.setCells(sheet.getCellsBuilder()
.set(cell.getReference().getRowIndex(), cell.getReference().getColumnIndex(), cell).build());
minColumns(sheet.getColumns(), cell.getReference().getColumnIndex() + 1);
minRows(sheet.getRows(), cell.getReference().getRowIndex() + 1);
}
public static void minColumns(List<ColumnData> columns, int minSize) {
while (columns.size() < minSize) {
columns.add(new ColumnData(columns.size(), 0, null));
}
}
public static void minRows(List<RowData> rows, int minSize) {
while (rows.size() < minSize) {
rows.add(new RowData(rows.size(), 0, null));
}
}
@Override
public synchronized void saveColumn(ColumnData column, Collection<ColumnData.Property> properties)
throws StorageException, NotFoundException {
List<ColumnData> columns = sheet.getColumns();
minColumns(columns, column.getIndex() + 1);
columns.set(column.getIndex(), column);
}
@Override
public synchronized void deleteColumn(int column) throws StorageException, NotFoundException {
if (column < sheet.getColumns().size()) {
sheet.getColumns().remove(column);
sheet.setCells(sheet.getCellsBuilder().removeColumn(column).build());
}
}
@Override
public synchronized void saveSheet(SheetData sheetData, Collection<SheetData.Property> properties)
throws StorageException, NotFoundException {
sheet.setSheetData(sheetData);
}
@Override
public SheetData loadSheet() throws StorageException, NotFoundException {
return sheet.getSheetData();
}
@Override
public void insertColumn(ColumnData column, Collection<Property> properties) {
// TODO Auto-generated method stub
}
@Override
public SheetDimensions getSheetDimensions() throws StorageException, NotFoundException {
return new SheetDimensions(sheet.getRows().size(), sheet.getColumns().size());
}
private void applyTransformer(CompleteSheet sheet, IReferenceTransformer referenceTransformer) {
MatrixBuilder<CellData> newCells = sheet.getCellsBuilder();
for (List<CellData> row : sheet.getCells().getRows()) {
for (CellData cell : row) {
if (cell == null) {
continue;
}
CellReference newRef = referenceTransformer.transform(cell.getReference());
if (newRef != null) {
CellData newCell = new CellData(newRef, cell.getValue(), cell.getFormula(), cell.getStyles());
newCells = newCells.set(newCell.getReference().getRowIndex(), newCell.getReference()
.getColumnIndex(), newCell);
}
}
}
sheet.setCells(newCells.build());
}
@Override
public void deleteSheet() throws StorageException, NotFoundException {
// nothing to do
}
}