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            protected TableHandler tableHandler;
015            protected final char separator;
016            protected List<TableContainer> containers;
017            protected final StringBuilder[] cachedSymbols;
018            protected 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                    setContainers(containers);
029                    initSymbolTable();
030                    cachedSymbols = new StringBuilder[containers.size()];
031                    cachedCodes = new int[containers.size()];
032                    for (int i = 0; i < containers.size(); i++) {
033                            cachedCodes[i] = -1;
034                            cachedSymbols[i] = new StringBuilder();
035                    };
036            }
037            
038            public void clearCache() {
039                    super.clearCache();
040                    for (int i = 0, n = cachedCodes.length; i < n; i++) {
041                            cachedCodes[i] = -1;
042                    }
043                    for (int i = 0, n = cachedSymbols.length; i < n; i++) {
044                            cachedSymbols[i].setLength(0);
045                    }
046            }
047            
048            public int addSymbol(String value) throws MaltChainedException {
049                    return table.addSymbol(value);
050            }
051    
052            public String getName() {
053                    return table.getName();
054            }
055    
056            public String getSymbolCodeToString(int code)
057                            throws MaltChainedException {
058                    return table.getSymbolCodeToString(code);
059            }
060    
061            public int getSymbolStringToCode(String symbol) throws MaltChainedException {
062                    return table.getSymbolStringToCode(symbol);
063            }
064            
065            public int getNumberContainers() {
066                    return containers.size();
067            }
068            
069            
070            /* override TableContainer */
071            public String getSymbol(int code) throws MaltChainedException {
072                    if (code < 0 && !containCode(code)) {
073                            clearCache();
074                            return null;
075                    }
076                    if (cachedCode != code) {
077                            clearCache();
078                            cachedCode = code;
079                            cachedSymbol.append(table.getSymbolCodeToString(cachedCode));
080                            split();
081                    }
082                    return cachedSymbol.toString();
083            }
084            
085            public int getCode(String symbol) throws MaltChainedException {
086                    if (cachedSymbol == null || !cachedSymbol.equals(symbol)) {
087                            clearCache();
088                            cachedSymbol.append(symbol);
089                            cachedCode = table.getSymbolStringToCode(symbol);
090                            split();
091                    }
092                    return cachedCode;
093            }
094            
095            public boolean containCode(int code) throws MaltChainedException {
096                    if (cachedCode != code) {
097                            clearCache();
098                            cachedSymbol.append(table.getSymbolCodeToString(code));
099                            if (cachedSymbol == null && cachedSymbol.length() == 0) {
100                                    return false;
101                            }
102                            cachedCode = code;
103                            split();
104                    }
105                    return true;
106            }
107            
108            public boolean containSymbol(String symbol) throws MaltChainedException {
109                    if (cachedSymbol == null || !cachedSymbol.equals(symbol)) {
110                            clearCache();
111                            cachedCode = table.getSymbolStringToCode(symbol);
112                            if (cachedCode < 0) {
113                                    return false;
114                            }
115                            cachedSymbol.append(symbol);
116                            split();
117                    }
118                    return true;
119            }
120            
121            
122            
123            public int getCombinedCode(List<ActionContainer> codesToCombine) throws MaltChainedException {
124                    boolean cachedUsed = true;
125                    if (containers.size() != codesToCombine.size()) {
126                            clearCache();
127                            return -1;
128                    }
129                    
130                    for (int i = 0, n = containers.size(); i < n; i++) {
131                            if (codesToCombine.get(i).getActionCode() != cachedCodes[i]) {
132                                    cachedUsed = false;
133                                    if (codesToCombine.get(i).getActionCode() >= 0 && containers.get(i).containCode(codesToCombine.get(i).getActionCode())) {
134                                            cachedSymbols[i].setLength(0);
135                                            cachedSymbols[i].append(containers.get(i).getSymbol(codesToCombine.get(i).getActionCode()));
136                                            cachedCodes[i] = codesToCombine.get(i).getActionCode(); 
137                                    } else {
138                                            cachedSymbols[i].setLength(0);
139                                            cachedCodes[i] = -1;
140                                    }
141                            }
142                    }
143            
144                    if (!cachedUsed) {
145                            cachedSymbol.setLength(0);
146                            for (int i = 0, n = containers.size(); i < n; i++) {
147                                    if (cachedSymbols[i].length() != 0) {
148                                            cachedSymbol.append(cachedSymbols[i]);
149                                            cachedSymbol.append(separator);
150                                    }
151                            }
152                            if (cachedSymbol.length() > 0) {
153                                    cachedSymbol.setLength(cachedSymbol.length()-1);
154                            }
155                            if (cachedSymbol.length() > 0) {
156                                    cachedCode = table.addSymbol(cachedSymbol.toString());
157                            } else {
158                                    cachedCode = -1;
159                            }
160                    }
161                    return cachedCode; 
162            }
163            
164            public void setActionContainer(List<ActionContainer> actionContainers, int decision) throws MaltChainedException {
165                    if (decision != cachedCode) {
166                            clearCache();
167                            if (decision != -1) {
168                                    cachedSymbol.append(table.getSymbolCodeToString(decision));
169                                    cachedCode = decision;
170                            }
171                            split();
172                    }
173    
174                    for (int i = 0, n = containers.size(); i < n; i++) {
175                            if (cachedSymbols[i].length() != 0) {
176                                    cachedCodes[i] = actionContainers.get(i).setAction(cachedSymbols[i].toString());
177                            } else {
178                                    cachedCodes[i] = actionContainers.get(i).setAction(null);
179                            }
180                    }
181            }
182            
183            protected void split() throws MaltChainedException {
184                    int j = 0;
185                    for (int i = 0, n = containers.size(); i < n; i++) {
186                            cachedSymbols[i].setLength(0);
187                    }
188                    for (int i = 0, n = cachedSymbol.length(); i < n; i++) {
189                            if (cachedSymbol.charAt(i) == separator) {
190                                    j++;
191                            } else {
192                                    cachedSymbols[j].append(cachedSymbol.charAt(i));
193                            }
194                    }
195                    for (int i = j+1, n = containers.size(); i < n; i++) {
196                            cachedSymbols[i].setLength(0);
197                    }
198                    for (int i = 0, n = containers.size(); i < n; i++) {
199                            if (cachedSymbols[i].length() != 0) {
200                                    cachedCodes[i] = containers.get(i).getCode(cachedSymbols[i].toString());
201                            } else {
202                                    cachedCodes[i] = -1;
203                            }
204                    }
205            }
206    
207            public char getSeparator() {
208                    return separator;
209            }
210    
211            public List<TableContainer> getContainers() {
212                    return containers;
213            }
214            
215            
216            protected void setContainers(List<TableContainer> containers) {
217                    this.containers = containers;
218            }
219            
220            protected void initSymbolTable() throws MaltChainedException {
221                    final StringBuilder sb = new StringBuilder();
222    
223                    for (TableContainer container : containers) {
224                            sb.append(container.getTableContainerName()+"+");
225                    }
226                    sb.setLength(sb.length()-1);
227                    setTable((Table)tableHandler.addSymbolTable(sb.toString())); 
228                    setName(sb.toString());
229            }
230    }