001package org.maltparser.core.feature.map;
002
003import org.maltparser.core.exception.MaltChainedException;
004import org.maltparser.core.feature.FeatureException;
005import org.maltparser.core.feature.function.FeatureFunction;
006import org.maltparser.core.feature.function.FeatureMapFunction;
007import org.maltparser.core.feature.value.FeatureValue;
008import org.maltparser.core.feature.value.SingleFeatureValue;
009import org.maltparser.core.io.dataformat.ColumnDescription;
010import org.maltparser.core.symbol.SymbolTable;
011import org.maltparser.core.symbol.SymbolTableHandler;
012/**
013*
014*
015* @author Johan Hall
016*/
017public final class Merge3Feature implements FeatureMapFunction {
018        public final static Class<?>[] paramTypes = {   org.maltparser.core.feature.function.FeatureFunction.class, 
019                                                            org.maltparser.core.feature.function.FeatureFunction.class, 
020                                                            org.maltparser.core.feature.function.FeatureFunction.class };
021        private FeatureFunction firstFeature;
022        private FeatureFunction secondFeature;
023        private FeatureFunction thirdFeature;
024        private final SymbolTableHandler tableHandler;
025        private SymbolTable table;
026        private final SingleFeatureValue singleFeatureValue;
027        private int type;
028        
029        public Merge3Feature(SymbolTableHandler tableHandler) throws MaltChainedException {
030                this.tableHandler = tableHandler;
031                this.singleFeatureValue = new SingleFeatureValue(this);
032        }
033        
034        public void initialize(Object[] arguments) throws MaltChainedException {
035                if (arguments.length != 3) {
036                        throw new FeatureException("Could not initialize Merge3Feature: number of arguments are not correct. ");
037                }
038                if (!(arguments[0] instanceof FeatureFunction)) {
039                        throw new FeatureException("Could not initialize Merge3Feature: the first argument is not a feature. ");
040                }
041                if (!(arguments[1] instanceof FeatureFunction)) {
042                        throw new FeatureException("Could not initialize Merge3Feature: the second argument is not a feature. ");
043                }
044                if (!(arguments[2] instanceof FeatureFunction)) {
045                        throw new FeatureException("Could not initialize Merge3Feature: the third argument is not a feature. ");
046                }
047                setFirstFeature((FeatureFunction)arguments[0]);
048                setSecondFeature((FeatureFunction)arguments[1]);
049                setThirdFeature((FeatureFunction)arguments[2]);
050                if (firstFeature.getType() != secondFeature.getType() || firstFeature.getType() != thirdFeature.getType()) {
051                        throw new FeatureException("Could not initialize MergeFeature: the arguments are not of the same type.");
052                }
053                this.type = firstFeature.getType();
054                String name = "MERGE3_"+firstFeature.getMapIdentifier()+"_"+secondFeature.getMapIdentifier()+"_"+thirdFeature.getMapIdentifier();
055                setSymbolTable(tableHandler.addSymbolTable(name,ColumnDescription.INPUT, ColumnDescription.STRING, "One"));
056        }
057        
058        public void update() throws MaltChainedException {
059                singleFeatureValue.reset();
060                firstFeature.update();
061                secondFeature.update();
062                thirdFeature.update();
063                FeatureValue firstValue = firstFeature.getFeatureValue();
064                FeatureValue secondValue = secondFeature.getFeatureValue();
065                FeatureValue thirdValue = thirdFeature.getFeatureValue();
066                if (firstValue.isMultiple() || secondValue.isMultiple() || thirdValue.isMultiple()) {
067                        throw new FeatureException("It is not possible to merge Split-features. ");
068                }
069
070                String firstSymbol = ((SingleFeatureValue)firstValue).getSymbol();
071                if (firstValue.isNullValue() && secondValue.isNullValue() && thirdValue.isNullValue()) {
072                        singleFeatureValue.setIndexCode(firstFeature.getSymbolTable().getSymbolStringToCode(firstSymbol));
073                        singleFeatureValue.setSymbol(firstSymbol);
074                        singleFeatureValue.setNullValue(true);
075                } else {
076                        if (getType() == ColumnDescription.STRING) { 
077                                StringBuilder mergedValue = new StringBuilder();
078                                mergedValue.append(((SingleFeatureValue)firstValue).getSymbol());
079                                mergedValue.append('~');
080                                mergedValue.append(((SingleFeatureValue)secondValue).getSymbol());
081                                mergedValue.append('~');
082                                mergedValue.append(((SingleFeatureValue)thirdValue).getSymbol());
083                                singleFeatureValue.setIndexCode(table.addSymbol(mergedValue.toString()));       
084                                singleFeatureValue.setSymbol(mergedValue.toString());
085                                singleFeatureValue.setNullValue(false);
086                                singleFeatureValue.setValue(1);
087                        } else {
088                                if (firstValue.isNullValue() || secondValue.isNullValue() || thirdValue.isNullValue()) {
089                                        singleFeatureValue.setValue(0);
090                                        table.addSymbol("#null#");
091                                        singleFeatureValue.setSymbol("#null#");
092                                        singleFeatureValue.setNullValue(true);
093                                        singleFeatureValue.setIndexCode(1);
094                                } else {
095                                        if (getType() == ColumnDescription.BOOLEAN) {
096                                                boolean result = false;
097                                                int dotIndex = firstSymbol.indexOf('.');
098                                                result = firstSymbol.equals("1") || firstSymbol.equals("true") ||  firstSymbol.equals("#true#") || (dotIndex != -1 && firstSymbol.substring(0,dotIndex).equals("1"));
099                                                if (result == true) {
100                                                        String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
101                                                        dotIndex = secondSymbol.indexOf('.');
102                                                        result = secondSymbol.equals("1") || secondSymbol.equals("true") ||  secondSymbol.equals("#true#") || (dotIndex != -1 && secondSymbol.substring(0,dotIndex).equals("1"));
103                                                }
104                                                if (result == true) {
105                                                        String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
106                                                        dotIndex = thirdSymbol.indexOf('.');
107                                                        result = thirdSymbol.equals("1") || thirdSymbol.equals("true") ||  thirdSymbol.equals("#true#") || (dotIndex != -1 && thirdSymbol.substring(0,dotIndex).equals("1"));
108                                                }
109                                                if (result) {
110                                                        singleFeatureValue.setValue(1);
111                                                        table.addSymbol("true");
112                                                        singleFeatureValue.setSymbol("true");
113                                                } else {
114                                                        singleFeatureValue.setValue(0);
115                                                        table.addSymbol("false");
116                                                        singleFeatureValue.setSymbol("false");
117                                                }
118                                        } else if (getType() == ColumnDescription.INTEGER) {
119                                                Integer firstInt = 0;
120                                                Integer secondInt = 0;
121                                                Integer thirdInt = 0;
122                                                
123                                                try {
124                                                        int dotIndex = firstSymbol.indexOf('.');
125                                                        if (dotIndex == -1) {
126                                                                firstInt = Integer.parseInt(firstSymbol);
127                                                        } else {
128                                                                firstInt = Integer.parseInt(firstSymbol.substring(0,dotIndex));
129                                                        }
130                                                } catch (NumberFormatException e) {
131                                                        throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to integer value.", e);
132                                                }
133                                                String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
134                                                try {
135                                                        int dotIndex = secondSymbol.indexOf('.');
136                                                        if (dotIndex == -1) {
137                                                                secondInt = Integer.parseInt(secondSymbol);
138                                                        } else {
139                                                                secondInt = Integer.parseInt(secondSymbol.substring(0,dotIndex));
140                                                        }
141                                                } catch (NumberFormatException e) {
142                                                        throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to integer value.", e);
143                                                }
144                                                String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
145                                                try {
146                                                        int dotIndex = thirdSymbol.indexOf('.');
147                                                        if (dotIndex == -1) {
148                                                                thirdInt = Integer.parseInt(thirdSymbol);
149                                                        } else {
150                                                                thirdInt = Integer.parseInt(thirdSymbol.substring(0,dotIndex));
151                                                        }
152                                                } catch (NumberFormatException e) {
153                                                        throw new FeatureException("Could not cast the feature value '"+thirdSymbol+"' to integer value.", e);
154                                                }
155                                                Integer result = firstInt*secondInt*thirdInt;
156                                                singleFeatureValue.setValue(result);
157                                                table.addSymbol(result.toString());
158                                                singleFeatureValue.setSymbol(result.toString());
159                                        } else if (getType() == ColumnDescription.REAL) {
160                                                Double firstReal = 0.0;
161                                                Double secondReal = 0.0;
162                                                Double thirdReal = 0.0;
163                                                try {
164                                                        firstReal = Double.parseDouble(firstSymbol);
165                                                } catch (NumberFormatException e) {
166                                                        throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to real value.", e);
167                                                }
168                                                String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
169                                                try {
170                                                        secondReal = Double.parseDouble(secondSymbol);
171                                                } catch (NumberFormatException e) {
172                                                        throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to real value.", e);
173                                                }
174                                                String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
175                                                try {
176                                                        thirdReal = Double.parseDouble(thirdSymbol);
177                                                } catch (NumberFormatException e) {
178                                                        throw new FeatureException("Could not cast the feature value '"+thirdSymbol+"' to real value.", e);
179                                                }
180                                                Double result = firstReal*secondReal*thirdReal;
181                                                singleFeatureValue.setValue(result);
182                                                table.addSymbol(result.toString());
183                                                singleFeatureValue.setSymbol(result.toString());
184                                        }
185                                        singleFeatureValue.setNullValue(false);
186                                        singleFeatureValue.setIndexCode(1);
187                                }
188                        }
189                }
190        }
191        
192        public Class<?>[] getParameterTypes() {
193                return paramTypes; 
194        }
195
196        public FeatureValue getFeatureValue() {
197                return singleFeatureValue;
198        }
199
200        public String getSymbol(int code) throws MaltChainedException {
201                return table.getSymbolCodeToString(code);
202        }
203        
204        public int getCode(String symbol) throws MaltChainedException {
205                return table.getSymbolStringToCode(symbol);
206        }
207        
208        public FeatureFunction getFirstFeature() {
209                return firstFeature;
210        }
211
212        public void setFirstFeature(FeatureFunction firstFeature) {
213                this.firstFeature = firstFeature;
214        }
215
216        public FeatureFunction getSecondFeature() {
217                return secondFeature;
218        }
219
220        public void setSecondFeature(FeatureFunction secondFeature) {
221                this.secondFeature = secondFeature;
222        }
223
224        public FeatureFunction getThirdFeature() {
225                return thirdFeature;
226        }
227
228        public void setThirdFeature(FeatureFunction thirdFeature) {
229                this.thirdFeature = thirdFeature;
230        }
231        
232        public SymbolTableHandler getTableHandler() {
233                return tableHandler;
234        }
235
236        public SymbolTable getSymbolTable() {
237                return table;
238        }
239
240        public void setSymbolTable(SymbolTable table) {
241                this.table = table;
242        }
243        
244        public  int getType() {
245                return type;
246        }
247        
248        public String getMapIdentifier() {
249                return getSymbolTable().getName();
250        }
251        
252        public boolean equals(Object obj) {
253                if (this == obj)
254                        return true;
255                if (obj == null)
256                        return false;
257                if (getClass() != obj.getClass())
258                        return false;
259                return obj.toString().equals(this.toString());
260        }
261        
262        public String toString() {
263                final StringBuilder sb = new StringBuilder();
264                sb.append("Merge3(");
265                sb.append(firstFeature.toString());
266                sb.append(", ");
267                sb.append(secondFeature.toString());
268                sb.append(", ");
269                sb.append(thirdFeature.toString());
270                sb.append(')');
271                return sb.toString();
272        }
273}