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