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