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, ColumnDescription.STRING, "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.setValue(1);
131        }
132
133        public ColumnDescription getColumn() {
134                return column;
135        }
136
137        public void setColumn(ColumnDescription column) throws MaltChainedException {
138                if (column.getType() != ColumnDescription.INTEGER) {
139                        throw new FeatureException("OutputArc feature column must be of type integer. ");
140                }
141                this.column = column;
142        }
143
144        /**
145         * Returns the address function 1 (argument 1) 
146         * 
147         * @return the address function 1 (argument 1) 
148         */
149        public AddressFunction getAddressFunction1() {
150                return addressFunction1;
151        }
152
153
154        /**
155         * Sets the address function 1 (argument 1) 
156         * 
157         * @param addressFunction1 a address function 1 (argument 1) 
158         */
159        public void setAddressFunction1(AddressFunction addressFunction1) {
160                this.addressFunction1 = addressFunction1;
161        }
162        
163        /**
164         * Returns the address function 2 (argument 2) 
165         * 
166         * @return the address function 1 (argument 2) 
167         */
168        public AddressFunction getAddressFunction2() {
169                return addressFunction2;
170        }
171
172        /**
173         * Sets the address function 2 (argument 2) 
174         * 
175         * @param addressFunction2 a address function 2 (argument 2) 
176         */
177        public void setAddressFunction2(AddressFunction addressFunction2) {
178                this.addressFunction2 = addressFunction2;
179        }
180        
181        public DataFormatInstance getDataFormatInstance() {
182                return dataFormatInstance;
183        }
184        
185        public SymbolTable getSymbolTable() {
186                return table;
187        }
188
189        public void setSymbolTable(SymbolTable table) {
190                this.table = table;
191        }
192        
193        public SymbolTableHandler getTableHandler() {
194                return tableHandler;
195        }
196        
197        public  int getType() {
198                return ColumnDescription.STRING;
199        }
200        
201        public String getMapIdentifier() {
202                return getSymbolTable().getName();
203        }
204        
205        public boolean equals(Object obj) {
206                if (!(obj instanceof InputArcFeature)) {
207                        return false;
208                }
209                if (!obj.toString().equals(this.toString())) {
210                        return false;
211                }
212                return true;
213        }
214        
215        public String toString() {
216                return "OutputArc(" + column.getName() + ")";
217        }
218}