package org.maltparser.parser.history.container;
import java.util.List;
import org.maltparser.core.exception.MaltChainedException;
import org.maltparser.core.symbol.Table;
import org.maltparser.core.symbol.TableHandler;
/**
*
* @author Johan Hall
* @since 1.1
*
*/
public class CombinedTableContainer extends TableContainer implements Table {
private TableHandler tableHandler;
private final char separator;
private final TableContainer[] containers;
private final StringBuilder[] cachedSymbols;
private final int[] cachedCodes;
public CombinedTableContainer(TableHandler tableHandler, String separator, List<TableContainer> containers, char decisionSeparator) throws MaltChainedException {
super(null, null, decisionSeparator);
this.tableHandler = tableHandler;
if (separator.length() > 0) {
this.separator = separator.charAt(0);
} else {
this.separator = '~';
}
this.containers = new TableContainer[containers.size()];
for (int i = 0; i < containers.size(); i++) {
this.containers[i] = containers.get(i);
}
initSymbolTable();
cachedSymbols = new StringBuilder[containers.size()];
cachedCodes = new int[containers.size()];
for (int i = 0; i < containers.size(); i++) {
cachedCodes[i] = -1;
cachedSymbols[i] = new StringBuilder();
}
}
@Override
public void clearCache() {
super.clearCache();
for (int i = 0; i < cachedCodes.length; i++) {
cachedCodes[i] = -1;
}
for (int i = 0; i < cachedSymbols.length; i++) {
cachedSymbols[i].setLength(0);
}
}
public int addSymbol(String value) throws MaltChainedException {
return table.addSymbol(value);
}
public String getName() {
return table.getName();
}
public String getSymbolCodeToString(int code)
throws MaltChainedException {
return table.getSymbolCodeToString(code);
}
public int getSymbolStringToCode(String symbol) throws MaltChainedException {
return table.getSymbolStringToCode(symbol);
}
public int getNumberContainers() {
return containers.length;
}
/*
* override TableContainer
*/
@Override
public String getSymbol(int code) throws MaltChainedException {
if (code < 0 && !containCode(code)) {
clearCache();
return null;
}
if (cachedCode != code) {
clearCache();
cachedCode = code;
cachedSymbol.append(table.getSymbolCodeToString(cachedCode));
split();
}
return cachedSymbol.toString();
}
@Override
public int getCode(String symbol) throws MaltChainedException {
if (cachedSymbol == null || !cachedSymbol.equals(symbol)) {
clearCache();
cachedSymbol.append(symbol);
cachedCode = table.getSymbolStringToCode(symbol);
split();
}
return cachedCode;
}
@Override
public boolean containCode(int code) throws MaltChainedException {
if (cachedCode != code) {
clearCache();
cachedSymbol.append(table.getSymbolCodeToString(code));
if (cachedSymbol == null && cachedSymbol.length() == 0) {
return false;
}
cachedCode = code;
split();
}
return true;
}
@Override
public boolean containSymbol(String symbol) throws MaltChainedException {
if (cachedSymbol == null || !cachedSymbol.equals(symbol)) {
clearCache();
cachedCode = table.getSymbolStringToCode(symbol);
if (cachedCode < 0) {
return false;
}
cachedSymbol.append(symbol);
split();
}
return true;
}
public int getCombinedCode(List<ActionContainer> codesToCombine) throws MaltChainedException {
boolean cachedUsed = true;
if (containers.length != codesToCombine.size()) {
clearCache();
return -1;
}
for (int i = 0; i < containers.length; i++) {
if (codesToCombine.get(i).getActionCode() != cachedCodes[i]) {
cachedUsed = false;
if (codesToCombine.get(i).getActionCode() >= 0 && containers[i].containCode(codesToCombine.get(i).getActionCode())) {
cachedSymbols[i].setLength(0);
cachedSymbols[i].append(containers[i].getSymbol(codesToCombine.get(i).getActionCode()));
cachedCodes[i] = codesToCombine.get(i).getActionCode();
} else {
cachedSymbols[i].setLength(0);
cachedCodes[i] = -1;
}
}
}
if (!cachedUsed) {
cachedSymbol.setLength(0);
for (int i = 0; i < containers.length; i++) {
if (cachedSymbols[i].length() != 0) {
cachedSymbol.append(cachedSymbols[i]);
cachedSymbol.append(separator);
}
}
if (cachedSymbol.length() > 0) {
cachedSymbol.setLength(cachedSymbol.length() - 1);
}
if (cachedSymbol.length() > 0) {
cachedCode = table.addSymbol(cachedSymbol.toString());
} else {
cachedCode = -1;
}
}
return cachedCode;
}
public int getCombinedCode(ActionContainer[] codesToCombine, int start) throws MaltChainedException {
boolean cachedUsed = true;
if (start < 0 || containers.length > (codesToCombine.length - start)) {
clearCache();
return -1;
}
for (int i = 0; i < containers.length; i++) {
int code = codesToCombine[i + start].getActionCode();
if (code != cachedCodes[i]) {
cachedUsed = false;
if (code >= 0 && containers[i].containCode(code)) {
cachedSymbols[i].setLength(0);
cachedSymbols[i].append(containers[i].getSymbol(code));
cachedCodes[i] = code;
} else {
cachedSymbols[i].setLength(0);
cachedCodes[i] = -1;
}
}
}
if (!cachedUsed) {
cachedSymbol.setLength(0);
for (int i = 0; i < containers.length; i++) {
if (cachedSymbols[i].length() != 0) {
cachedSymbol.append(cachedSymbols[i]);
cachedSymbol.append(separator);
}
}
if (cachedSymbol.length() > 0) {
cachedSymbol.setLength(cachedSymbol.length() - 1);
}
if (cachedSymbol.length() > 0) {
cachedCode = table.addSymbol(cachedSymbol.toString());
} else {
cachedCode = -1;
}
}
return cachedCode;
}
public void setActionContainer(List<ActionContainer> actionContainers, int decision) throws MaltChainedException {
if (decision != cachedCode) {
clearCache();
if (decision != -1) {
cachedSymbol.append(table.getSymbolCodeToString(decision));
cachedCode = decision;
}
split();
}
for (int i = 0; i < containers.length; i++) {
if (cachedSymbols[i].length() != 0) {
cachedCodes[i] = actionContainers.get(i).setAction(cachedSymbols[i].toString());
} else {
cachedCodes[i] = actionContainers.get(i).setAction(null);
}
}
}
public void setActionContainer(ActionContainer[] actionContainers, int start, int decision) throws MaltChainedException {
if (decision != cachedCode) {
clearCache();
if (decision != -1) {
cachedSymbol.append(table.getSymbolCodeToString(decision));
cachedCode = decision;
}
split();
}
for (int i = 0; i < containers.length; i++) {
if (cachedSymbols[i].length() != 0) {
cachedCodes[i] = actionContainers[i + start].setAction(cachedSymbols[i].toString());
} else {
cachedCodes[i] = actionContainers[i + start].setAction(null);
}
}
}
protected void split() throws MaltChainedException {
int j = 0;
for (int i = 0; i < containers.length; i++) {
cachedSymbols[i].setLength(0);
}
for (int i = 0; i < cachedSymbol.length(); i++) {
if (cachedSymbol.charAt(i) == separator) {
j++;
} else {
cachedSymbols[j].append(cachedSymbol.charAt(i));
}
}
for (int i = j + 1; i < containers.length; i++) {
cachedSymbols[i].setLength(0);
}
for (int i = 0; i < containers.length; i++) {
if (cachedSymbols[i].length() != 0) {
cachedCodes[i] = containers[i].getCode(cachedSymbols[i].toString());
} else {
cachedCodes[i] = -1;
}
}
}
public char getSeparator() {
return separator;
}
protected void initSymbolTable() throws MaltChainedException {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < containers.length; i++) {
sb.append(containers[i]).append(getTableContainerName()).append("+");
}
sb.setLength(sb.length() - 1);
setTable((Table) tableHandler.addSymbolTable(sb.toString()));
setName(sb.toString());
}
}