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,"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
067                if (firstValue instanceof SingleFeatureValue && secondValue instanceof SingleFeatureValue && thirdValue instanceof SingleFeatureValue) {
068                        String firstSymbol = ((SingleFeatureValue)firstValue).getSymbol();
069                        if (firstValue.isNullValue() && secondValue.isNullValue() && thirdValue.isNullValue()) {
070                                singleFeatureValue.setIndexCode(firstFeature.getSymbolTable().getSymbolStringToCode(firstSymbol));
071                                singleFeatureValue.setSymbol(firstSymbol);
072                                singleFeatureValue.setNullValue(true);
073                        } else {
074                                if (getType() == ColumnDescription.STRING) { 
075                                        StringBuilder mergedValue = new StringBuilder();
076                                        mergedValue.append(((SingleFeatureValue)firstValue).getSymbol());
077                                        mergedValue.append('~');
078                                        mergedValue.append(((SingleFeatureValue)secondValue).getSymbol());
079                                        mergedValue.append('~');
080                                        mergedValue.append(((SingleFeatureValue)thirdValue).getSymbol());
081                                        singleFeatureValue.setIndexCode(table.addSymbol(mergedValue.toString()));       
082                                        singleFeatureValue.setSymbol(mergedValue.toString());
083                                        singleFeatureValue.setNullValue(false);
084                                        singleFeatureValue.setValue(1);
085                                } else {
086                                        if (firstValue.isNullValue() || secondValue.isNullValue() || thirdValue.isNullValue()) {
087                                                singleFeatureValue.setValue(0);
088                                                table.addSymbol("#null#");
089                                                singleFeatureValue.setSymbol("#null#");
090                                                singleFeatureValue.setNullValue(true);
091                                                singleFeatureValue.setIndexCode(1);
092                                        } else {
093                                                if (getType() == ColumnDescription.BOOLEAN) {
094                                                        boolean result = false;
095                                                        int dotIndex = firstSymbol.indexOf('.');
096                                                        result = firstSymbol.equals("1") || firstSymbol.equals("true") ||  firstSymbol.equals("#true#") || (dotIndex != -1 && firstSymbol.substring(0,dotIndex).equals("1"));
097                                                        if (result == true) {
098                                                                String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
099                                                                dotIndex = secondSymbol.indexOf('.');
100                                                                result = secondSymbol.equals("1") || secondSymbol.equals("true") ||  secondSymbol.equals("#true#") || (dotIndex != -1 && secondSymbol.substring(0,dotIndex).equals("1"));
101                                                        }
102                                                        if (result == true) {
103                                                                String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
104                                                                dotIndex = thirdSymbol.indexOf('.');
105                                                                result = thirdSymbol.equals("1") || thirdSymbol.equals("true") ||  thirdSymbol.equals("#true#") || (dotIndex != -1 && thirdSymbol.substring(0,dotIndex).equals("1"));
106                                                        }
107                                                        if (result) {
108                                                                singleFeatureValue.setValue(1);
109                                                                table.addSymbol("true");
110                                                                singleFeatureValue.setSymbol("true");
111                                                        } else {
112                                                                singleFeatureValue.setValue(0);
113                                                                table.addSymbol("false");
114                                                                singleFeatureValue.setSymbol("false");
115                                                        }
116                                                } else if (getType() == ColumnDescription.INTEGER) {
117                                                        Integer firstInt = 0;
118                                                        Integer secondInt = 0;
119                                                        Integer thirdInt = 0;
120                                                        
121                                                        try {
122                                                                int dotIndex = firstSymbol.indexOf('.');
123                                                                if (dotIndex == -1) {
124                                                                        firstInt = Integer.parseInt(firstSymbol);
125                                                                } else {
126                                                                        firstInt = Integer.parseInt(firstSymbol.substring(0,dotIndex));
127                                                                }
128                                                        } catch (NumberFormatException e) {
129                                                                throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to integer value.", e);
130                                                        }
131                                                        String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
132                                                        try {
133                                                                int dotIndex = secondSymbol.indexOf('.');
134                                                                if (dotIndex == -1) {
135                                                                        secondInt = Integer.parseInt(secondSymbol);
136                                                                } else {
137                                                                        secondInt = Integer.parseInt(secondSymbol.substring(0,dotIndex));
138                                                                }
139                                                        } catch (NumberFormatException e) {
140                                                                throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to integer value.", e);
141                                                        }
142                                                        String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
143                                                        try {
144                                                                int dotIndex = thirdSymbol.indexOf('.');
145                                                                if (dotIndex == -1) {
146                                                                        secondInt = Integer.parseInt(thirdSymbol);
147                                                                } else {
148                                                                        secondInt = Integer.parseInt(thirdSymbol.substring(0,dotIndex));
149                                                                }
150                                                        } catch (NumberFormatException e) {
151                                                                throw new FeatureException("Could not cast the feature value '"+thirdSymbol+"' to integer value.", e);
152                                                        }
153                                                        Integer result = firstInt*secondInt*thirdInt;
154                                                        singleFeatureValue.setValue(result);
155                                                        table.addSymbol(result.toString());
156                                                        singleFeatureValue.setSymbol(result.toString());
157                                                } else if (getType() == ColumnDescription.REAL) {
158                                                        Double firstReal = 0.0;
159                                                        Double secondReal = 0.0;
160                                                        Double thirdReal = 0.0;
161                                                        try {
162                                                                firstReal = Double.parseDouble(firstSymbol);
163                                                        } catch (NumberFormatException e) {
164                                                                throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to real value.", e);
165                                                        }
166                                                        String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
167                                                        try {
168                                                                secondReal = Double.parseDouble(secondSymbol);
169                                                        } catch (NumberFormatException e) {
170                                                                throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to real value.", e);
171                                                        }
172                                                        String thirdSymbol = ((SingleFeatureValue)thirdValue).getSymbol();
173                                                        try {
174                                                                thirdReal = Double.parseDouble(thirdSymbol);
175                                                        } catch (NumberFormatException e) {
176                                                                throw new FeatureException("Could not cast the feature value '"+thirdSymbol+"' to real value.", e);
177                                                        }
178                                                        Double result = firstReal*secondReal*thirdReal;
179                                                        singleFeatureValue.setValue(result);
180                                                        table.addSymbol(result.toString());
181                                                        singleFeatureValue.setSymbol(result.toString());
182                                                }
183                                                singleFeatureValue.setNullValue(false);
184                                                singleFeatureValue.setIndexCode(1);
185                                        }
186                                }
187                        }
188                } else {
189                        throw new FeatureException("It is not possible to merge Split-features. ");
190                }
191        }
192        
193        public Class<?>[] getParameterTypes() {
194                return paramTypes; 
195        }
196
197        public FeatureValue getFeatureValue() {
198                return singleFeatureValue;
199        }
200
201        public String getSymbol(int code) throws MaltChainedException {
202                return table.getSymbolCodeToString(code);
203        }
204        
205        public int getCode(String symbol) throws MaltChainedException {
206                return table.getSymbolStringToCode(symbol);
207        }
208        
209        public FeatureFunction getFirstFeature() {
210                return firstFeature;
211        }
212
213        public void setFirstFeature(FeatureFunction firstFeature) {
214                this.firstFeature = firstFeature;
215        }
216
217        public FeatureFunction getSecondFeature() {
218                return secondFeature;
219        }
220
221        public void setSecondFeature(FeatureFunction secondFeature) {
222                this.secondFeature = secondFeature;
223        }
224
225        public FeatureFunction getThirdFeature() {
226                return thirdFeature;
227        }
228
229        public void setThirdFeature(FeatureFunction thirdFeature) {
230                this.thirdFeature = thirdFeature;
231        }
232        
233        public SymbolTableHandler getTableHandler() {
234                return tableHandler;
235        }
236
237        public SymbolTable getSymbolTable() {
238                return table;
239        }
240
241        public void setSymbolTable(SymbolTable table) {
242                this.table = table;
243        }
244        
245        public  int getType() {
246                return type;
247        }
248        
249        public String getMapIdentifier() {
250                return getSymbolTable().getName();
251        }
252        
253        public boolean equals(Object obj) {
254                if (this == obj)
255                        return true;
256                if (obj == null)
257                        return false;
258                if (getClass() != obj.getClass())
259                        return false;
260                return obj.toString().equals(this.toString());
261        }
262        
263        public String toString() {
264                final StringBuilder sb = new StringBuilder();
265                sb.append("Merge3(");
266                sb.append(firstFeature.toString());
267                sb.append(", ");
268                sb.append(secondFeature.toString());
269                sb.append(", ");
270                sb.append(thirdFeature.toString());
271                sb.append(')');
272                return sb.toString();
273        }
274}