001package org.maltparser.core.syntaxgraph.node;
002
003import java.util.Iterator;
004import java.util.SortedSet;
005import java.util.TreeSet;
006
007import org.maltparser.core.exception.MaltChainedException;
008import org.maltparser.core.syntaxgraph.GraphElement;
009import org.maltparser.core.syntaxgraph.SyntaxGraphException;
010import org.maltparser.core.syntaxgraph.edge.Edge;
011
012
013
014/**
015 * 
016 * 
017 * @author Johan Hall
018 *
019 */
020public abstract class GraphNode extends GraphElement implements Node {
021        protected SortedSet<Edge> incomingEdges;
022        protected SortedSet<Edge> outgoingEdges;
023        
024        public GraphNode() throws MaltChainedException {
025                super();
026                incomingEdges = new TreeSet<Edge>();
027                outgoingEdges = new TreeSet<Edge>();
028        }
029        
030        public void addIncomingEdge(Edge in) throws MaltChainedException {
031                if (in.getTarget() != this) {
032                        throw new SyntaxGraphException("The incoming edge's 'to' reference is not correct.");
033                }
034                incomingEdges.add(in);
035        }
036        
037        public void addOutgoingEdge(Edge out) throws MaltChainedException {
038                if (out.getSource() != this) {
039                        throw new SyntaxGraphException("The outgoing edge's 'from' reference is not correct");
040                }
041                outgoingEdges.add(out);
042        }
043
044        public void removeIncomingEdge(Edge in) throws MaltChainedException {
045                if (in.getTarget() != this) {
046                        throw new SyntaxGraphException("The incoming edge's 'to' reference is not correct");
047                }
048                incomingEdges.remove(in);
049        }
050
051        public void removeOutgoingEdge(Edge out) throws MaltChainedException {
052                if (out.getSource() != this) {
053                        throw new SyntaxGraphException("The outgoing edge's 'from' reference is not correct");
054                }
055                outgoingEdges.remove(out);
056        }
057
058        public int getLeftmostProperDescendantIndex() throws MaltChainedException {
059                ComparableNode node = getLeftmostProperDescendant();
060                return (node != null)?node.getIndex():-1;
061        }
062        
063        public int getRightmostProperDescendantIndex() throws MaltChainedException {
064                ComparableNode node = getRightmostProperDescendant();
065                return (node != null)?node.getIndex():-1;
066        }
067        
068        public int getLeftmostDescendantIndex() throws MaltChainedException {
069                ComparableNode node = getLeftmostProperDescendant();
070                return (node != null)?node.getIndex():this.getIndex();
071        }
072        
073        public int getRightmostDescendantIndex() throws MaltChainedException {
074                ComparableNode node = getRightmostProperDescendant();
075                return (node != null)?node.getIndex():this.getIndex();
076        }
077        
078        public Iterator<Edge> getIncomingEdgeIterator() {
079                return incomingEdges.iterator();
080        }
081        
082        public Iterator<Edge> getOutgoingEdgeIterator() {
083                return outgoingEdges.iterator();
084        }
085        
086        public void clear() throws MaltChainedException {
087                super.clear();
088                incomingEdges.clear();
089                outgoingEdges.clear();
090        }
091        
092        public int getInDegree() {
093                return incomingEdges.size();
094        }
095        
096        public int getOutDegree() {
097                return outgoingEdges.size();
098        }
099        
100        public SortedSet<Edge> getIncomingSecondaryEdges() {
101                SortedSet<Edge> inSecEdges = new TreeSet<Edge>();
102                for (Edge e : incomingEdges) {
103                        if (e.getType() == Edge.SECONDARY_EDGE) {
104                                inSecEdges.add(e);
105                        }
106                }
107                return inSecEdges;
108        }
109        
110        public SortedSet<Edge> getOutgoingSecondaryEdges() {
111                SortedSet<Edge> outSecEdges = new TreeSet<Edge>();
112                for (Edge e : outgoingEdges) {
113                        if (e.getType() == Edge.SECONDARY_EDGE) {
114                                outSecEdges.add(e);
115                        }
116                }
117                return outSecEdges;
118        }
119        
120        public int compareTo(ComparableNode o) {                
121                return super.compareTo((GraphElement)o);
122        }
123        
124        public abstract int getIndex();
125        public abstract void setIndex(int index) throws MaltChainedException;
126        public abstract boolean isRoot();
127        
128        public boolean equals(Object obj) {
129                GraphNode v = (GraphNode)obj;
130                return super.equals(obj) && incomingEdges.equals(v.incomingEdges) 
131                                && outgoingEdges.equals(v.outgoingEdges); 
132        }
133        
134        public int hashCode() {
135                int hash = 7;
136                hash = 31 * hash + super.hashCode();
137                hash = 31 * hash + (null == incomingEdges ? 0 : incomingEdges.hashCode());
138                hash = 31 * hash + (null == outgoingEdges ? 0 : outgoingEdges.hashCode());
139                return hash;
140        }
141        
142        public String toString() {
143                final StringBuilder sb = new StringBuilder();
144                sb.append(getIndex());
145                sb.append(" [I:");
146                for (Edge e : incomingEdges) {
147                        sb.append(e.getSource().getIndex());
148                        sb.append("(");
149                        sb.append(e.toString());
150                        sb.append(")");
151                        if (incomingEdges.last() != e) {
152                                sb.append(",");
153                        }
154                }
155                sb.append("][O:");
156                for (Edge e : outgoingEdges) {
157                        sb.append(e.getTarget().getIndex());
158                        if (outgoingEdges.last() != e) {
159                                sb.append(",");
160                        }
161                }
162                sb.append("]");
163                sb.append(super.toString());
164                return sb.toString();
165        }
166}