001 package org.maltparser.parser.history.container; 002 003 import java.util.List; 004 005 import org.maltparser.core.exception.MaltChainedException; 006 import org.maltparser.core.symbol.Table; 007 import org.maltparser.core.symbol.TableHandler; 008 /** 009 * 010 * @author Johan Hall 011 * @since 1.1 012 **/ 013 public class CombinedTableContainer extends TableContainer implements Table { 014 private TableHandler tableHandler; 015 private final char separator; 016 private final TableContainer[] containers; 017 private final StringBuilder[] cachedSymbols; 018 private final int[] cachedCodes; 019 020 public CombinedTableContainer(TableHandler tableHandler, String separator, List<TableContainer> containers, char decisionSeparator) throws MaltChainedException { 021 super(null, null, decisionSeparator); 022 this.tableHandler = tableHandler; 023 if (separator.length() > 0) { 024 this.separator = separator.charAt(0); 025 } else { 026 this.separator = '~'; 027 }; 028 this.containers = new TableContainer[containers.size()]; 029 for (int i = 0; i < containers.size(); i++) { 030 this.containers[i] = containers.get(i); 031 } 032 initSymbolTable(); 033 cachedSymbols = new StringBuilder[containers.size()]; 034 cachedCodes = new int[containers.size()]; 035 for (int i = 0; i < containers.size(); i++) { 036 cachedCodes[i] = -1; 037 cachedSymbols[i] = new StringBuilder(); 038 }; 039 } 040 041 public void clearCache() { 042 super.clearCache(); 043 for (int i = 0; i < cachedCodes.length; i++) { 044 cachedCodes[i] = -1; 045 } 046 for (int i = 0; i < cachedSymbols.length; i++) { 047 cachedSymbols[i].setLength(0); 048 } 049 } 050 051 public int addSymbol(String value) throws MaltChainedException { 052 return table.addSymbol(value); 053 } 054 055 public String getName() { 056 return table.getName(); 057 } 058 059 public String getSymbolCodeToString(int code) 060 throws MaltChainedException { 061 return table.getSymbolCodeToString(code); 062 } 063 064 public int getSymbolStringToCode(String symbol) throws MaltChainedException { 065 return table.getSymbolStringToCode(symbol); 066 } 067 068 public int getNumberContainers() { 069 return containers.length; 070 } 071 072 073 /* override TableContainer */ 074 public String getSymbol(int code) throws MaltChainedException { 075 if (code < 0 && !containCode(code)) { 076 clearCache(); 077 return null; 078 } 079 if (cachedCode != code) { 080 clearCache(); 081 cachedCode = code; 082 cachedSymbol.append(table.getSymbolCodeToString(cachedCode)); 083 split(); 084 } 085 return cachedSymbol.toString(); 086 } 087 088 public int getCode(String symbol) throws MaltChainedException { 089 if (cachedSymbol == null || !cachedSymbol.equals(symbol)) { 090 clearCache(); 091 cachedSymbol.append(symbol); 092 cachedCode = table.getSymbolStringToCode(symbol); 093 split(); 094 } 095 return cachedCode; 096 } 097 098 public boolean containCode(int code) throws MaltChainedException { 099 if (cachedCode != code) { 100 clearCache(); 101 cachedSymbol.append(table.getSymbolCodeToString(code)); 102 if (cachedSymbol == null && cachedSymbol.length() == 0) { 103 return false; 104 } 105 cachedCode = code; 106 split(); 107 } 108 return true; 109 } 110 111 public boolean containSymbol(String symbol) throws MaltChainedException { 112 if (cachedSymbol == null || !cachedSymbol.equals(symbol)) { 113 clearCache(); 114 cachedCode = table.getSymbolStringToCode(symbol); 115 if (cachedCode < 0) { 116 return false; 117 } 118 cachedSymbol.append(symbol); 119 split(); 120 } 121 return true; 122 } 123 124 public int getCombinedCode(List<ActionContainer> codesToCombine) throws MaltChainedException { 125 boolean cachedUsed = true; 126 if (containers.length != codesToCombine.size()) { 127 clearCache(); 128 return -1; 129 } 130 131 for (int i = 0; i < containers.length; i++) { 132 if (codesToCombine.get(i).getActionCode() != cachedCodes[i]) { 133 cachedUsed = false; 134 if (codesToCombine.get(i).getActionCode() >= 0 && containers[i].containCode(codesToCombine.get(i).getActionCode())) { 135 cachedSymbols[i].setLength(0); 136 cachedSymbols[i].append(containers[i].getSymbol(codesToCombine.get(i).getActionCode())); 137 cachedCodes[i] = codesToCombine.get(i).getActionCode(); 138 } else { 139 cachedSymbols[i].setLength(0); 140 cachedCodes[i] = -1; 141 } 142 } 143 } 144 145 if (!cachedUsed) { 146 cachedSymbol.setLength(0); 147 for (int i = 0; i < containers.length; i++) { 148 if (cachedSymbols[i].length() != 0) { 149 cachedSymbol.append(cachedSymbols[i]); 150 cachedSymbol.append(separator); 151 } 152 } 153 if (cachedSymbol.length() > 0) { 154 cachedSymbol.setLength(cachedSymbol.length()-1); 155 } 156 if (cachedSymbol.length() > 0) { 157 cachedCode = table.addSymbol(cachedSymbol.toString()); 158 } else { 159 cachedCode = -1; 160 } 161 } 162 return cachedCode; 163 } 164 165 public int getCombinedCode(ActionContainer[] codesToCombine, int start) throws MaltChainedException { 166 boolean cachedUsed = true; 167 if (start < 0 || containers.length > (codesToCombine.length - start)) { 168 clearCache(); 169 return -1; 170 } 171 172 for (int i = 0; i < containers.length; i++) { 173 int code = codesToCombine[i+start].getActionCode(); 174 if (code != cachedCodes[i]) { 175 cachedUsed = false; 176 if (code >= 0 && containers[i].containCode(code)) { 177 cachedSymbols[i].setLength(0); 178 cachedSymbols[i].append(containers[i].getSymbol(code)); 179 cachedCodes[i] = code; 180 } else { 181 cachedSymbols[i].setLength(0); 182 cachedCodes[i] = -1; 183 } 184 } 185 } 186 187 if (!cachedUsed) { 188 cachedSymbol.setLength(0); 189 for (int i = 0; i < containers.length; i++) { 190 if (cachedSymbols[i].length() != 0) { 191 cachedSymbol.append(cachedSymbols[i]); 192 cachedSymbol.append(separator); 193 } 194 } 195 if (cachedSymbol.length() > 0) { 196 cachedSymbol.setLength(cachedSymbol.length()-1); 197 } 198 if (cachedSymbol.length() > 0) { 199 cachedCode = table.addSymbol(cachedSymbol.toString()); 200 } else { 201 cachedCode = -1; 202 } 203 } 204 return cachedCode; 205 } 206 207 208 public void setActionContainer(List<ActionContainer> actionContainers, int decision) throws MaltChainedException { 209 if (decision != cachedCode) { 210 clearCache(); 211 if (decision != -1) { 212 cachedSymbol.append(table.getSymbolCodeToString(decision)); 213 cachedCode = decision; 214 } 215 split(); 216 } 217 218 for (int i = 0; i < containers.length; i++) { 219 if (cachedSymbols[i].length() != 0) { 220 cachedCodes[i] = actionContainers.get(i).setAction(cachedSymbols[i].toString()); 221 } else { 222 cachedCodes[i] = actionContainers.get(i).setAction(null); 223 } 224 } 225 } 226 227 public void setActionContainer(ActionContainer[] actionContainers, int start, int decision) throws MaltChainedException { 228 if (decision != cachedCode) { 229 clearCache(); 230 if (decision != -1) { 231 cachedSymbol.append(table.getSymbolCodeToString(decision)); 232 cachedCode = decision; 233 } 234 split(); 235 } 236 237 for (int i = 0; i < containers.length; i++) { 238 if (cachedSymbols[i].length() != 0) { 239 cachedCodes[i] = actionContainers[i+start].setAction(cachedSymbols[i].toString()); 240 } else { 241 cachedCodes[i] = actionContainers[i+start].setAction(null); 242 } 243 } 244 } 245 246 protected void split() throws MaltChainedException { 247 int j = 0; 248 for (int i = 0; i < containers.length; i++) { 249 cachedSymbols[i].setLength(0); 250 } 251 for (int i = 0; i < cachedSymbol.length(); i++) { 252 if (cachedSymbol.charAt(i) == separator) { 253 j++; 254 } else { 255 cachedSymbols[j].append(cachedSymbol.charAt(i)); 256 } 257 } 258 for (int i = j+1; i < containers.length; i++) { 259 cachedSymbols[i].setLength(0); 260 } 261 for (int i = 0; i < containers.length; i++) { 262 if (cachedSymbols[i].length() != 0) { 263 cachedCodes[i] = containers[i].getCode(cachedSymbols[i].toString()); 264 } else { 265 cachedCodes[i] = -1; 266 } 267 } 268 } 269 270 public char getSeparator() { 271 return separator; 272 } 273 274 protected void initSymbolTable() throws MaltChainedException { 275 final StringBuilder sb = new StringBuilder(); 276 for (int i = 0; i < containers.length; i++) { 277 sb.append(containers[i].getTableContainerName()+"+"); 278 } 279 sb.setLength(sb.length()-1); 280 setTable((Table)tableHandler.addSymbolTable(sb.toString())); 281 setName(sb.toString()); 282 } 283 }