001package org.maltparser.core.symbol.parse;
002
003import java.io.BufferedReader;
004import java.io.BufferedWriter;
005import java.util.Map;
006
007import org.maltparser.core.exception.MaltChainedException;
008import org.maltparser.core.helper.HashMap;
009import org.maltparser.core.symbol.SymbolException;
010import org.maltparser.core.symbol.SymbolTable;
011import org.maltparser.core.symbol.SymbolTableHandler;
012
013import org.maltparser.core.symbol.nullvalue.NullValues.NullValueId;
014
015
016public class ParseSymbolTable implements SymbolTable {
017        private final String name;
018        private final SymbolTable parentSymbolTable;
019    
020        /** Special treatment during parsing */
021        private final Map<String, Integer> symbolCodeMap;
022        private final Map<Integer, String> codeSymbolMap;
023        private int valueCounter;
024    
025        public ParseSymbolTable(String name, int columnCategory, String nullValueStrategy, SymbolTableHandler parentSymbolTableHandler) throws MaltChainedException {
026                this.name = name;
027                this.parentSymbolTable = parentSymbolTableHandler.addSymbolTable(name, columnCategory, nullValueStrategy);
028                this.symbolCodeMap = new HashMap<String, Integer>();
029                this.codeSymbolMap = new HashMap<Integer, String>();
030                this.valueCounter = -1;
031        }
032        
033        public ParseSymbolTable(String name, SymbolTable parentTable, SymbolTableHandler parentSymbolTableHandler) throws MaltChainedException {
034                this.name = name;
035                this.parentSymbolTable = parentSymbolTableHandler.addSymbolTable(name, parentTable);
036                this.symbolCodeMap = new HashMap<String, Integer>();
037                this.codeSymbolMap = new HashMap<Integer, String>();
038                this.valueCounter = -1;
039        }
040        
041        public ParseSymbolTable(String name, SymbolTableHandler parentSymbolTableHandler) throws MaltChainedException {
042                this.name = name;
043                this.parentSymbolTable = parentSymbolTableHandler.addSymbolTable(name);
044                this.symbolCodeMap = new HashMap<String, Integer>();
045                this.codeSymbolMap = new HashMap<Integer, String>();
046                this.valueCounter = -1;
047        }
048        
049        public int addSymbol(String symbol) throws MaltChainedException {
050                if (!parentSymbolTable.isNullValue(symbol)) {
051                        if (symbol == null || symbol.length() == 0) {
052                                throw new SymbolException("Symbol table error: empty string cannot be added to the symbol table");
053                        }
054
055                        int code = parentSymbolTable.getSymbolStringToCode(symbol); 
056                        if (code > -1) {
057                                return code;
058                        }
059                        if (!symbolCodeMap.containsKey(symbol)) {
060//                              System.out.println("!symbolCodeMap.containsKey(symbol) : " + this.getName() + ": " + symbol.toString());
061                                if (valueCounter == -1) {
062                                        valueCounter = parentSymbolTable.getValueCounter() + 1;
063                                } else {
064                                        valueCounter++;
065                                }
066                                symbolCodeMap.put(symbol, valueCounter);
067                                codeSymbolMap.put(valueCounter, symbol);
068                                return valueCounter;
069                        } else {
070                                return symbolCodeMap.get(symbol);
071                        }
072                } else {
073                        return parentSymbolTable.getSymbolStringToCode(symbol);
074                }
075        }
076        
077//      public int addSymbol(StringBuilder symbol) throws MaltChainedException {
078//              return addSymbol(symbol.toString());
079//      }
080        
081        public String getSymbolCodeToString(int code) throws MaltChainedException {
082                if (code >= 0) {
083                        if (!parentSymbolTable.isNullValue(code)) {
084                                String symbol = parentSymbolTable.getSymbolCodeToString(code); 
085                                if (symbol != null) {
086                                        return symbol;
087                                } else {
088                                        if (!codeSymbolMap.containsKey(code)) {
089                                                throw new SymbolException("The symbol code '"+code+"' cannot be found in the symbol table. ");
090                                        }
091                                        return codeSymbolMap.get(code);
092                                }
093                        } else {
094                                return parentSymbolTable.getSymbolCodeToString(code);
095                        }
096                } else {
097                        throw new SymbolException("The symbol code '"+code+"' cannot be found in the symbol table. ");
098                }
099        }
100        
101        public int getSymbolStringToCode(String symbol) throws MaltChainedException {
102                if (symbol != null) {
103                        if (!parentSymbolTable.isNullValue(symbol)) {
104                                int code = parentSymbolTable.getSymbolStringToCode(symbol); 
105                                if (code > -1) {
106                                        return code;
107                                }
108                                if (!symbolCodeMap.containsKey(symbol)) {
109                                        throw new SymbolException("Could not find the symbol '"+symbol+"' in the symbol table. "); 
110                                }
111                                Integer item = symbolCodeMap.get(symbol);
112                                if (item == null) {
113                                        throw new SymbolException("Could not find the symbol '"+symbol+"' in the symbol table. "); 
114                                } 
115                                return item.intValue();
116                        } else {
117                                return parentSymbolTable.getSymbolStringToCode(symbol);
118                        }
119                } else {
120                        throw new SymbolException("The symbol code '"+symbol+"' cannot be found in the symbol table. ");
121                }
122        }
123
124        public void clearTmpStorage() {
125                symbolCodeMap.clear();
126                codeSymbolMap.clear();
127                valueCounter = -1;
128        }
129        
130//      public String getNullValueStrategy() {
131//              return parentSymbolTable.getNullValueStrategy();
132//      }
133//      
134//      
135//      public int getColumnCategory() {
136//              return parentSymbolTable.getColumnCategory();
137//      }
138        
139        public String printSymbolTable() throws MaltChainedException {
140                return parentSymbolTable.printSymbolTable();
141        }
142        
143//      public void saveHeader(BufferedWriter out) throws MaltChainedException  {
144//              parentSymbolTable.saveHeader(out);
145//      }
146        
147        public int size() {
148                return parentSymbolTable.size();
149        }
150        
151        
152        public void save(BufferedWriter out) throws MaltChainedException  {
153                parentSymbolTable.save(out);
154        }
155        
156        public void load(BufferedReader in) throws MaltChainedException {
157                parentSymbolTable.load(in);
158        }
159        
160        public String getName() {
161                return name;
162        }
163
164        public int getValueCounter() {
165                return parentSymbolTable.getValueCounter();
166        }
167
168        
169        public int getNullValueCode(NullValueId nullValueIdentifier) throws MaltChainedException {
170                return parentSymbolTable.getNullValueCode(nullValueIdentifier);
171        }
172        
173        public String getNullValueSymbol(NullValueId nullValueIdentifier) throws MaltChainedException {
174                return parentSymbolTable.getNullValueSymbol(nullValueIdentifier);
175        }
176        
177        public boolean isNullValue(String symbol) throws MaltChainedException {
178                return parentSymbolTable.isNullValue(symbol);
179        }
180        
181        public boolean isNullValue(int code) throws MaltChainedException {
182                return parentSymbolTable.isNullValue(code);
183        }
184        
185        public boolean equals(Object obj) {
186                if (this == obj)
187                        return true;
188                if (obj == null)
189                        return false;
190                if (getClass() != obj.getClass())
191                        return false;
192                final ParseSymbolTable other = (ParseSymbolTable)obj;
193                return ((name == null) ? other.name == null : name.equals(other.name));
194        }
195
196        public int hashCode() {
197                return 217 + (null == name ? 0 : name.hashCode());
198        }
199        
200        public String toString() {
201                return parentSymbolTable.toString();
202        }
203}