001package org.maltparser.core.syntaxgraph.feature;
002
003import org.maltparser.core.exception.MaltChainedException;
004import org.maltparser.core.feature.FeatureException;
005import org.maltparser.core.feature.function.AddressFunction;
006import org.maltparser.core.feature.function.FeatureFunction;
007import org.maltparser.core.feature.value.AddressValue;
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.io.dataformat.DataFormatInstance;
012import org.maltparser.core.symbol.SymbolTable;
013import org.maltparser.core.symbol.SymbolTableHandler;
014import org.maltparser.core.symbol.nullvalue.NullValues.NullValueId;
015import org.maltparser.core.syntaxgraph.SyntaxGraphException;
016import org.maltparser.core.syntaxgraph.node.DependencyNode;
017/**
018*
019* @author Johan Hall
020**/
021public final class InputArcFeature implements FeatureFunction {
022        public final static Class<?>[] paramTypes = { java.lang.String.class, org.maltparser.core.feature.function.AddressFunction.class, org.maltparser.core.feature.function.AddressFunction.class };
023        private AddressFunction addressFunction1;
024        private AddressFunction addressFunction2;
025        private ColumnDescription column;
026        private final DataFormatInstance dataFormatInstance;
027        private final SymbolTableHandler tableHandler;
028        private SymbolTable table;
029        private final SingleFeatureValue featureValue;
030
031        
032        public InputArcFeature(DataFormatInstance dataFormatInstance, SymbolTableHandler tableHandler) throws MaltChainedException {
033                this.dataFormatInstance = dataFormatInstance;
034                this.tableHandler = tableHandler;
035                this.featureValue = new SingleFeatureValue(this);
036        }
037        
038        public void initialize(Object[] arguments) throws MaltChainedException {
039                if (arguments.length != 3) {
040                        throw new FeatureException("Could not initialize InputArcFeature: number of arguments are not correct. ");
041                }
042                // Checks that the two arguments are address functions
043
044                if (!(arguments[0] instanceof String)) {
045                        throw new FeatureException("Could not initialize InputArcFeature: the first argument is not a string. ");
046                }
047                if (!(arguments[1] instanceof AddressFunction)) {
048                        throw new SyntaxGraphException("Could not initialize InputArcFeature: the second argument is not an address function. ");
049                }
050                if (!(arguments[2] instanceof AddressFunction)) {
051                        throw new SyntaxGraphException("Could not initialize InputArcFeature: the third argument is not an address function. ");
052                }
053                setAddressFunction1((AddressFunction)arguments[1]);
054                setAddressFunction2((AddressFunction)arguments[2]);
055                
056                setColumn(dataFormatInstance.getColumnDescriptionByName((String)arguments[0]));
057                setSymbolTable(tableHandler.addSymbolTable("ARC_"+column.getName(),ColumnDescription.INPUT, ColumnDescription.STRING, "one"));
058                table.addSymbol("LEFT");
059                table.addSymbol("RIGHT");
060        }
061        
062        public Class<?>[] getParameterTypes() {
063                return paramTypes;
064        }
065        
066        public int getCode(String symbol) throws MaltChainedException {
067                return table.getSymbolStringToCode(symbol);
068        }
069
070
071        public FeatureValue getFeatureValue() {
072                return featureValue;
073        }
074
075
076        public String getSymbol(int code) throws MaltChainedException {
077                return table.getSymbolCodeToString(code);
078        }
079
080
081        public void updateCardinality() throws MaltChainedException {
082//              featureValue.setCardinality(table.getValueCounter());
083        }
084
085        public void update() throws MaltChainedException {
086                // Retrieve the address value 
087                final AddressValue arg1 = addressFunction1.getAddressValue();
088                final AddressValue arg2 = addressFunction2.getAddressValue();
089                if (arg1.getAddress() != null && arg1.getAddressClass() == org.maltparser.core.syntaxgraph.node.DependencyNode.class &&
090                    arg2.getAddress() != null && arg2.getAddressClass() == org.maltparser.core.syntaxgraph.node.DependencyNode.class) {
091                    DependencyNode node1 = (DependencyNode)arg1.getAddress();
092                    DependencyNode node2 = (DependencyNode)arg2.getAddress();
093                    try {
094                    SymbolTable symbolTable = tableHandler.getSymbolTable(column.getName());
095                        int head1 = Integer.parseInt(node1.getLabelSymbol(symbolTable));
096                        int head2 = Integer.parseInt(node2.getLabelSymbol(symbolTable));
097                        if (!node1.isRoot() && head1 == node2.getIndex()) {
098                            featureValue.setIndexCode(table.getSymbolStringToCode("LEFT"));
099                            featureValue.setSymbol("LEFT");
100                            featureValue.setNullValue(false);
101                        } else if (!node2.isRoot() && head2 == node1.getIndex()) {
102                            featureValue.setIndexCode(table.getSymbolStringToCode("RIGHT"));
103                            featureValue.setSymbol("RIGHT");
104                            featureValue.setNullValue(false);                   
105                        } else {
106                            featureValue.setIndexCode(table.getNullValueCode(NullValueId.NO_NODE));
107                            featureValue.setSymbol(table.getNullValueSymbol(NullValueId.NO_NODE));
108                            featureValue.setNullValue(true);
109                        }
110                    } catch (NumberFormatException e) {
111                        throw new FeatureException("The index of the feature must be an integer value. ", e);
112                    }
113                } else {
114                    featureValue.setIndexCode(table.getNullValueCode(NullValueId.NO_NODE));
115                    featureValue.setSymbol(table.getNullValueSymbol(NullValueId.NO_NODE));
116                    featureValue.setNullValue(true);
117                }
118                featureValue.setValue(1);
119        }
120
121        public ColumnDescription getColumn() {
122                return column;
123        }
124
125        public void setColumn(ColumnDescription column) throws MaltChainedException {
126                if (column.getType() != ColumnDescription.INTEGER) {
127                        throw new FeatureException("InputArc feature column must be of type integer. ");
128                }
129                this.column = column;
130        }
131
132        /**
133         * Returns the address function 1 (argument 1) 
134         * 
135         * @return the address function 1 (argument 1) 
136         */
137        public AddressFunction getAddressFunction1() {
138                return addressFunction1;
139        }
140
141
142        /**
143         * Sets the address function 1 (argument 1) 
144         * 
145         * @param addressFunction1 a address function 1 (argument 1) 
146         */
147        public void setAddressFunction1(AddressFunction addressFunction1) {
148                this.addressFunction1 = addressFunction1;
149        }
150        
151        /**
152         * Returns the address function 2 (argument 2) 
153         * 
154         * @return the address function 1 (argument 2) 
155         */
156        public AddressFunction getAddressFunction2() {
157                return addressFunction2;
158        }
159
160        /**
161         * Sets the address function 2 (argument 2) 
162         * 
163         * @param addressFunction2 a address function 2 (argument 2) 
164         */
165        public void setAddressFunction2(AddressFunction addressFunction2) {
166                this.addressFunction2 = addressFunction2;
167        }
168        
169        public DataFormatInstance getDataFormatInstance() {
170                return dataFormatInstance;
171        }
172        
173        public SymbolTable getSymbolTable() {
174                return table;
175        }
176
177        public void setSymbolTable(SymbolTable table) {
178                this.table = table;
179        }
180        
181        public SymbolTableHandler getTableHandler() {
182                return tableHandler;
183        }
184        
185        public  int getType() {
186                return ColumnDescription.STRING;
187        }
188        
189        public String getMapIdentifier() {
190                return getSymbolTable().getName();
191        }
192        
193        public boolean equals(Object obj) {
194                if (!(obj instanceof InputArcFeature)) {
195                        return false;
196                }
197                if (!obj.toString().equals(this.toString())) {
198                        return false;
199                }
200                return true;
201        }
202        
203        public String toString() {
204                return "InputArc(" + column.getName() + ")";
205        }
206}