001package org.maltparser.parser.algorithm.nivre;
002
003import java.util.Stack;
004
005import org.maltparser.core.exception.MaltChainedException;
006import org.maltparser.core.syntaxgraph.DependencyStructure;
007import org.maltparser.core.syntaxgraph.node.DependencyNode;
008import org.maltparser.parser.ParserConfiguration;
009import org.maltparser.parser.ParsingException;
010/**
011 * @author Johan Hall
012 *
013 */
014public class NivreConfig extends ParserConfiguration {
015        private final Stack<DependencyNode> stack;
016        private final Stack<DependencyNode> input;
017        private DependencyStructure dependencyGraph;
018        private final boolean allowRoot;
019        private final boolean allowReduce;
020        private final boolean enforceTree;
021        
022    private boolean end; //Added
023        
024        public NivreConfig(boolean allowRoot, boolean allowReduce, boolean enforceTree) throws MaltChainedException {
025                super();
026                this.stack = new Stack<DependencyNode>();
027                this.input = new Stack<DependencyNode>();
028                this.allowRoot = allowRoot;
029                this.allowReduce = allowReduce;
030                this.enforceTree = enforceTree;
031                this.end = false; // Added 
032        }
033        
034        public Stack<DependencyNode> getStack() {
035                return stack;
036        }
037        
038        public Stack<DependencyNode> getInput() {
039                return input;
040        }
041        
042        public DependencyStructure getDependencyStructure() {
043                return dependencyGraph;
044        }
045        
046        public boolean isTerminalState() {
047                if (isEnforceTree()) {
048                        return input.isEmpty() && stack.size() == 1;
049                }
050                return input.isEmpty();
051        }
052        
053        public DependencyNode getStackNode(int index) throws MaltChainedException {
054                if (index < 0) {
055                        throw new ParsingException("Stack index must be non-negative in feature specification. ");
056                }
057                if (stack.size()-index > 0) {
058                        return stack.get(stack.size()-1-index);
059                }
060                return null;
061        }
062        
063        public DependencyNode getInputNode(int index) throws MaltChainedException {
064                if (index < 0) {
065                        throw new ParsingException("Input index must be non-negative in feature specification. ");
066                }
067                if (input.size()-index > 0) {
068                        return input.get(input.size()-1-index);
069                }       
070                return null;
071        }
072        
073        public void setDependencyGraph(DependencyStructure source) throws MaltChainedException {
074                this.dependencyGraph = source;
075        }
076        
077        public DependencyStructure getDependencyGraph() {
078                return dependencyGraph;
079        }
080        
081        public void initialize(ParserConfiguration parserConfiguration) throws MaltChainedException {
082                if (parserConfiguration != null) {
083                        final NivreConfig nivreConfig = (NivreConfig)parserConfiguration;
084                        final Stack<DependencyNode> sourceStack = nivreConfig.getStack();
085                        final Stack<DependencyNode> sourceInput = nivreConfig.getInput();
086                        setDependencyGraph(nivreConfig.getDependencyGraph());
087                        for (int i = 0, n = sourceStack.size(); i < n; i++) {
088                                stack.add(dependencyGraph.getDependencyNode(sourceStack.get(i).getIndex()));
089                        }
090                        for (int i = 0, n = sourceInput.size(); i < n; i++) {
091                                input.add(dependencyGraph.getDependencyNode(sourceInput.get(i).getIndex()));
092                        }
093                } else {
094                        stack.push(dependencyGraph.getDependencyRoot());
095                        for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) {
096                                final DependencyNode node = dependencyGraph.getDependencyNode(i);
097                                if (node != null && !node.hasHead()) { // added !node.hasHead()
098                                        input.push(node);
099                                }
100                        }
101                }
102        }
103        
104        public void initialize() throws MaltChainedException {
105                stack.push(dependencyGraph.getDependencyRoot());
106                for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) {
107                        final DependencyNode node = dependencyGraph.getDependencyNode(i);
108                        if (node != null && !node.hasHead()) { // added !node.hasHead()
109                                input.push(node);
110                        }
111                }
112        }
113        
114        public void setEnd(boolean end) {
115                this.end = end;
116        }
117                                                                                                                                                             
118    public boolean isEnd() {
119        return end;
120        }
121    
122    public boolean isAllowRoot() {
123        return allowRoot;
124        }
125        
126        public boolean isAllowReduce() {
127                return allowReduce;
128        }
129        
130        public boolean isEnforceTree() {
131                return enforceTree;
132        }
133
134        public void clear() throws MaltChainedException {
135                stack.clear();
136                input.clear();
137                historyNode = null;
138                end = false; // Added
139        }
140        
141        public boolean equals(Object obj) {
142                if (this == obj)
143                        return true;
144                if (obj == null)
145                        return false;
146                if (getClass() != obj.getClass())
147                        return false;
148                NivreConfig that = (NivreConfig)obj;
149                
150                if (stack.size() != that.getStack().size()) 
151                        return false;
152                if (input.size() != that.getInput().size())
153                        return false;
154                if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges())
155                        return false;
156                for (int i = 0; i < stack.size(); i++) {
157                        if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) {
158                                return false;
159                        }
160                }
161                for (int i = 0; i < input.size(); i++) {
162                        if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) {
163                                return false;
164                        }
165                }               
166                return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges());
167        }
168        
169        public String toString() {
170                final StringBuilder sb = new StringBuilder();
171                sb.append(stack.size());
172                sb.append(", ");
173                sb.append(input.size());
174                sb.append(", ");
175                sb.append(dependencyGraph.nEdges());
176                sb.append(", ");
177                sb.append(allowRoot);           
178                sb.append(", ");
179                sb.append(allowReduce);         
180                sb.append(", ");
181                sb.append(enforceTree);
182                return sb.toString();
183        }
184}