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