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