RandomSec/main/java/com/metaweb/gridworks/model/ColumnModel.java
Stefano Mazzocchi 365868564f create 'main' and 'server'
git-svn-id: http://google-refine.googlecode.com/svn/branches/split-refactor@905 7d457c2a-affb-35e4-300a-418c747d4874
2010-05-30 16:52:50 +00:00

245 lines
8.0 KiB
Java

package com.metaweb.gridworks.model;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.metaweb.gridworks.Jsonizable;
public class ColumnModel implements Jsonizable {
final public List<Column> columns = new LinkedList<Column>();
final public List<ColumnGroup> columnGroups = new LinkedList<ColumnGroup>();
private int _maxCellIndex;
private int _keyColumnIndex;
transient protected Map<String, Column> _nameToColumn;
transient protected Map<Integer, Column> _cellIndexToColumn;
transient protected List<ColumnGroup> _rootColumnGroups;
transient protected List<String> _columnNames;
public ColumnModel() {
internalInitialize();
}
synchronized public void setMaxCellIndex(int maxCellIndex) {
this._maxCellIndex = Math.max(this._maxCellIndex, maxCellIndex);
}
public int getMaxCellIndex() {
return _maxCellIndex;
}
synchronized public int allocateNewCellIndex() {
return ++_maxCellIndex;
}
public void setKeyColumnIndex(int keyColumnIndex) {
// TODO: check validity of new cell index, e.g., it's not in any group
this._keyColumnIndex = keyColumnIndex;
}
public int getKeyColumnIndex() {
return _keyColumnIndex;
}
synchronized public void addColumnGroup(int startColumnIndex, int span, int keyColumnIndex) {
for (ColumnGroup g : columnGroups) {
if (g.startColumnIndex == startColumnIndex && g.columnSpan == span) {
if (g.keyColumnIndex == keyColumnIndex) {
return;
} else {
columnGroups.remove(g);
break;
}
}
}
ColumnGroup cg = new ColumnGroup(startColumnIndex, span, keyColumnIndex);
columnGroups.add(cg);
}
public void update() {
internalInitialize();
}
synchronized public void addColumn(int index, Column column, boolean avoidNameCollision) throws ModelException {
String baseName = column.getName();
if (_nameToColumn.containsKey(baseName)) {
if (!avoidNameCollision) {
throw new ModelException("Duplicated column name");
}
}
String name = baseName;
int i = 1;
while (true) {
if (_nameToColumn.containsKey(name)) {
i++;
name = baseName + i;
} else {
break;
}
}
column.setName(name);
columns.add(index < 0 ? columns.size() : index, column);
_nameToColumn.put(name, column); // so the next call can check
}
synchronized public Column getColumnByName(String name) {
return _nameToColumn.get(name);
}
synchronized public int getColumnIndexByName(String name) {
for (int i = 0; i < _columnNames.size(); i++) {
String s = _columnNames.get(i);
if (name.equals(s)) {
return i;
}
}
return -1;
}
synchronized public Column getColumnByCellIndex(int cellIndex) {
return _cellIndexToColumn.get(cellIndex);
}
synchronized public List<String> getColumnNames() {
return _columnNames;
}
synchronized public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("columns");
writer.array();
for (Column column : columns) {
column.write(writer, options);
}
writer.endArray();
if (columns.size() > 0) {
writer.key("keyCellIndex"); writer.value(getKeyColumnIndex());
writer.key("keyColumnName"); writer.value(columns.get(_keyColumnIndex).getName());
}
writer.key("columnGroups");
writer.array();
for (ColumnGroup g : _rootColumnGroups) {
g.write(writer, options);
}
writer.endArray();
writer.endObject();
}
synchronized public void save(Writer writer, Properties options) throws IOException {
writer.write("maxCellIndex="); writer.write(Integer.toString(_maxCellIndex)); writer.write('\n');
writer.write("keyColumnIndex="); writer.write(Integer.toString(_keyColumnIndex)); writer.write('\n');
writer.write("columnCount="); writer.write(Integer.toString(columns.size())); writer.write('\n');
for (Column column : columns) {
column.save(writer); writer.write('\n');
}
writer.write("columnGroupCount="); writer.write(Integer.toString(columnGroups.size())); writer.write('\n');
for (ColumnGroup group : columnGroups) {
group.save(writer); writer.write('\n');
}
writer.write("/e/\n");
}
synchronized public void load(LineNumberReader reader) throws Exception {
String line;
while ((line = reader.readLine()) != null && !"/e/".equals(line)) {
int equal = line.indexOf('=');
CharSequence field = line.subSequence(0, equal);
String value = line.substring(equal + 1);
if ("maxCellIndex".equals(field)) {
_maxCellIndex = Integer.parseInt(value);
} else if ("keyColumnIndex".equals(field)) {
_keyColumnIndex = Integer.parseInt(value);
} else if ("columnCount".equals(field)) {
int count = Integer.parseInt(value);
for (int i = 0; i < count; i++) {
columns.add(Column.load(reader.readLine()));
}
} else if ("columnGroupCount".equals(field)) {
int count = Integer.parseInt(value);
for (int i = 0; i < count; i++) {
columnGroups.add(ColumnGroup.load(reader.readLine()));
}
}
}
internalInitialize();
}
synchronized protected void internalInitialize() {
generateMaps();
// Turn the flat list of column groups into a tree
_rootColumnGroups = new LinkedList<ColumnGroup>(columnGroups);
Collections.sort(_rootColumnGroups, new Comparator<ColumnGroup>() {
public int compare(ColumnGroup o1, ColumnGroup o2) {
int firstDiff = o1.startColumnIndex - o2.startColumnIndex;
return firstDiff != 0 ?
firstDiff : // whichever group that starts first goes first
(o2.columnSpan - o1.columnSpan); // otherwise, the larger group goes first
}
});
for (int i = _rootColumnGroups.size() - 1; i >= 0; i--) {
ColumnGroup g = _rootColumnGroups.get(i);
for (int j = i + 1; j < _rootColumnGroups.size(); j++) {
ColumnGroup g2 = _rootColumnGroups.get(j);
if (g2.parentGroup == null && g.contains(g2)) {
g2.parentGroup = g;
g.subgroups.add(g2);
}
}
}
for (int i = _rootColumnGroups.size() - 1; i >= 0; i--) {
if (_rootColumnGroups.get(i).parentGroup != null) {
_rootColumnGroups.remove(i);
}
}
}
protected void generateMaps() {
_nameToColumn = new HashMap<String, Column>();
_cellIndexToColumn = new HashMap<Integer, Column>();
_columnNames = new ArrayList<String>();
for (Column column : columns) {
_nameToColumn.put(column.getName(), column);
_cellIndexToColumn.put(column.getCellIndex(), column);
_columnNames.add(column.getName());
}
}
}