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 }