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