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()); } }