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