001package org.maltparser.core.syntaxgraph.feature;
002
003import org.maltparser.core.exception.MaltChainedException;
004import org.maltparser.core.feature.function.AddressFunction;
005import org.maltparser.core.feature.function.FeatureFunction;
006import org.maltparser.core.feature.value.FeatureValue;
007import org.maltparser.core.feature.value.SingleFeatureValue;
008import org.maltparser.core.io.dataformat.ColumnDescription;
009import org.maltparser.core.symbol.SymbolTable;
010import org.maltparser.core.symbol.SymbolTableHandler;
011import org.maltparser.core.symbol.nullvalue.NullValues.NullValueId;
012import org.maltparser.core.syntaxgraph.SyntaxGraphException;
013import org.maltparser.core.syntaxgraph.node.DependencyNode;
014
015public final class ArcDirFeature implements FeatureFunction {
016        public final static Class<?>[] paramTypes = { org.maltparser.core.feature.function.AddressFunction.class };
017        private AddressFunction addressFunction;
018        private final SymbolTableHandler tableHandler;
019        private SymbolTable table;
020        private final SingleFeatureValue featureValue;
021        
022        public ArcDirFeature(SymbolTableHandler tableHandler) throws MaltChainedException {
023                this.tableHandler = tableHandler;
024                this.featureValue = new SingleFeatureValue(this);
025        }
026        
027        /**
028         * Initialize the exists feature function
029         * 
030         * @param arguments an array of arguments with the type returned by getParameterTypes()
031         * @throws MaltChainedException
032         */
033        public void initialize(Object[] arguments) throws MaltChainedException {
034                if (arguments.length != 1) {
035                        throw new SyntaxGraphException("Could not initialize ArcDirFeature: number of arguments are not correct. ");
036                }
037                // Checks that the two arguments are address functions
038                if (!(arguments[0] instanceof AddressFunction)) {
039                        throw new SyntaxGraphException("Could not initialize ArcDirFeature: the first argument is not an address function. ");
040                }
041
042                setAddressFunction((AddressFunction)arguments[0]);
043                
044                // Creates a symbol table called "ARCDIR" using one null value
045                setSymbolTable(tableHandler.addSymbolTable("ARCDIR", ColumnDescription.INPUT, ColumnDescription.STRING, "one"));
046                
047                table.addSymbol("LEFT"); // The address exists
048                table.addSymbol("RIGHT"); // The address don't exists
049        }
050        
051        /**
052         * Returns an array of class types used by the feature extraction system to invoke initialize with
053         * correct arguments.
054         * 
055         * @return an array of class types
056         */
057        public Class<?>[] getParameterTypes() {
058                return paramTypes; 
059        }
060        /**
061         * Returns the string representation of the integer <code>code</code> according to the exists feature function. 
062         * 
063         * @param code the integer representation of the symbol
064         * @return the string representation of the integer <code>code</code> according to the exists feature function.
065         * @throws MaltChainedException
066         */
067        public String getSymbol(int code) throws MaltChainedException {
068                return table.getSymbolCodeToString(code);
069        }
070        
071        /**
072         * Returns the integer representation of the string <code>symbol</code> according to the exists feature function.
073         * 
074         * @param symbol the string representation of the symbol
075         * @return the integer representation of the string <code>symbol</code> according to the exists feature function.
076         * @throws MaltChainedException
077         */
078        public int getCode(String symbol) throws MaltChainedException {
079                return table.getSymbolStringToCode(symbol);
080        }
081        
082        /**
083         * Cause the feature function to update the feature value.
084         * 
085         * @throws MaltChainedException
086         */
087        public void update() throws MaltChainedException {
088                if (addressFunction.getAddressValue().getAddress() != null) {
089                        final DependencyNode node = (DependencyNode)addressFunction.getAddressValue().getAddress();
090                        if (!node.isRoot()) { 
091                                if (node.getHead().getIndex() < node.getIndex()) {
092                                        featureValue.setIndexCode(table.getSymbolStringToCode("LEFT"));
093                                        featureValue.setValue(1);
094                                        featureValue.setSymbol("LEFT");
095                                        featureValue.setNullValue(false);
096                                } else {
097                                        featureValue.setIndexCode(table.getSymbolStringToCode("RIGHT"));
098                                        featureValue.setValue(1);
099                                        featureValue.setSymbol("RIGHT");
100                                        featureValue.setNullValue(false);
101                                }
102                        } else { 
103                                featureValue.setIndexCode(table.getNullValueCode(NullValueId.ROOT_NODE));
104                                featureValue.setValue(1);
105                                featureValue.setSymbol(table.getNullValueSymbol(NullValueId.ROOT_NODE));
106                                featureValue.setNullValue(true);
107                        }
108                } else {
109                        featureValue.setIndexCode(table.getNullValueCode(NullValueId.NO_NODE));
110                        featureValue.setValue(1);
111                        featureValue.setSymbol(table.getNullValueSymbol(NullValueId.NO_NODE));
112                        featureValue.setNullValue(true);
113                }
114        }
115        
116        /**
117         * Returns the feature value
118         * 
119         * @return the feature value
120         */
121        public FeatureValue getFeatureValue() {
122                return featureValue;
123        }
124        
125        /**
126         * Returns the symbol table used by the exists feature function
127         * 
128         * @return the symbol table used by the exists feature function
129         */
130        public SymbolTable getSymbolTable() {
131                return table;
132        }
133        
134        /**
135         * Returns the address function 
136         * 
137         * @return the address function 
138         */
139        public AddressFunction getAddressFunction() {
140                return addressFunction;
141        }
142
143
144        /**
145         * Sets the address function 
146         * 
147         * @param addressFunction a address function 
148         */
149        public void setAddressFunction(AddressFunction addressFunction) {
150                this.addressFunction = addressFunction;
151        }
152        
153        /**
154         * Returns symbol table handler
155         * 
156         * @return a symbol table handler
157         */
158        public SymbolTableHandler getTableHandler() {
159                return tableHandler;
160        }
161
162        public  int getType() {
163                return ColumnDescription.STRING;
164        }
165        
166        public String getMapIdentifier() {
167                return getSymbolTable().getName();
168        }
169        /**
170         * Sets the symbol table used by the exists feature function
171         * 
172         * @param table
173         */
174        public void setSymbolTable(SymbolTable table) {
175                this.table = table;
176        }
177        
178        public boolean equals(Object obj) {
179                if (this == obj)
180                        return true;
181                if (obj == null)
182                        return false;
183                if (getClass() != obj.getClass())
184                        return false;
185                return obj.toString().equals(this.toString());
186        }
187        
188        public int hashCode() {
189                return 217 + (null == toString() ? 0 : toString().hashCode());
190        }
191        
192        public String toString() {
193                final StringBuilder sb = new StringBuilder();
194                sb.append("ArcDir(");
195                sb.append(addressFunction.toString());
196                sb.append(')');
197                return sb.toString();
198        }
199}