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,"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 instanceof SingleFeatureValue && secondValue instanceof SingleFeatureValue) {
060                        String firstSymbol = ((SingleFeatureValue)firstValue).getSymbol();
061                        if (firstValue.isNullValue() && secondValue.isNullValue()) {
062                                singleFeatureValue.setIndexCode(firstFeature.getSymbolTable().getSymbolStringToCode(firstSymbol));
063                                singleFeatureValue.setSymbol(firstSymbol);
064                                singleFeatureValue.setNullValue(true);
065                        } else {
066                                if (getType() == ColumnDescription.STRING) { 
067                                        StringBuilder mergedValue = new StringBuilder();
068                                        mergedValue.append(firstSymbol);
069                                        mergedValue.append('~');
070                                        mergedValue.append(((SingleFeatureValue)secondValue).getSymbol());
071                                        singleFeatureValue.setIndexCode(table.addSymbol(mergedValue.toString()));
072                                        singleFeatureValue.setSymbol(mergedValue.toString());
073                                        singleFeatureValue.setNullValue(false);
074                                        singleFeatureValue.setValue(1);
075                                } else {
076                                        if (firstValue.isNullValue() || secondValue.isNullValue()) {
077                                                singleFeatureValue.setValue(0);
078                                                table.addSymbol("#null#");
079                                                singleFeatureValue.setSymbol("#null#");
080                                                singleFeatureValue.setNullValue(true);
081                                                singleFeatureValue.setIndexCode(1);
082                                        } else {
083                                                if (getType() == ColumnDescription.BOOLEAN) {
084                                                        boolean result = false;
085                                                        int dotIndex = firstSymbol.indexOf('.');
086                                                        result = firstSymbol.equals("1") || firstSymbol.equals("true") ||  firstSymbol.equals("#true#") || (dotIndex != -1 && firstSymbol.substring(0,dotIndex).equals("1"));
087                                                        if (result == true) {
088                                                                String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
089                                                                dotIndex = secondSymbol.indexOf('.');
090                                                                result = secondSymbol.equals("1") || secondSymbol.equals("true") ||  secondSymbol.equals("#true#") || (dotIndex != -1 && secondSymbol.substring(0,dotIndex).equals("1"));
091                                                        }
092                                                        if (result) {
093                                                                singleFeatureValue.setValue(1);
094                                                                table.addSymbol("true");
095                                                                singleFeatureValue.setSymbol("true");
096                                                        } else {
097                                                                singleFeatureValue.setValue(0);
098                                                                table.addSymbol("false");
099                                                                singleFeatureValue.setSymbol("false");
100                                                        }
101                                                } else if (getType() == ColumnDescription.INTEGER) {
102                                                        Integer firstInt = 0;
103                                                        Integer secondInt = 0;
104                                                        
105                                                        int dotIndex = firstSymbol.indexOf('.');
106                                                        try {
107                                                                if (dotIndex == -1) {
108                                                                        firstInt = Integer.parseInt(firstSymbol);
109                                                                } else {
110                                                                        firstInt = Integer.parseInt(firstSymbol.substring(0,dotIndex));
111                                                                }
112                                                        } catch (NumberFormatException e) {
113                                                                throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to integer value.", e);
114                                                        }
115                                                        String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
116                                                        dotIndex = secondSymbol.indexOf('.');
117                                                        try {
118                                                                if (dotIndex == -1) {
119                                                                        secondInt = Integer.parseInt(secondSymbol);
120                                                                } else {
121                                                                        secondInt = Integer.parseInt(secondSymbol.substring(0,dotIndex));
122                                                                }
123                                                        } catch (NumberFormatException e) {
124                                                                throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to integer value.", e);
125                                                        }
126                                                        Integer result = firstInt*secondInt;
127                                                        singleFeatureValue.setValue(result);
128                                                        table.addSymbol(result.toString());
129                                                        singleFeatureValue.setSymbol(result.toString());
130                                                } else if (getType() == ColumnDescription.REAL) {
131                                                        Double firstReal = 0.0;
132                                                        Double secondReal = 0.0;
133                                                        try {
134                                                                firstReal = Double.parseDouble(firstSymbol);
135                                                        } catch (NumberFormatException e) {
136                                                                throw new FeatureException("Could not cast the feature value '"+firstSymbol+"' to real value.", e);
137                                                        }
138                                                        String secondSymbol = ((SingleFeatureValue)secondValue).getSymbol();
139                                                        try {
140                                                                secondReal = Double.parseDouble(secondSymbol);
141                                                        } catch (NumberFormatException e) {
142                                                                throw new FeatureException("Could not cast the feature value '"+secondSymbol+"' to real value.", e);
143                                                        }
144                                                        Double result = firstReal*secondReal;
145                                                        singleFeatureValue.setValue(result);
146                                                        table.addSymbol(result.toString());
147                                                        singleFeatureValue.setSymbol(result.toString());
148                                                }
149                                                singleFeatureValue.setNullValue(false);
150                                                singleFeatureValue.setIndexCode(1);
151                                        }
152                                }
153                        }
154                } else {
155                        throw new FeatureException("It is not possible to merge Split-features. ");
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}