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