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    }