001    package org.maltparser.core.syntaxgraph.node;
002    
003    import java.util.Iterator;
004    import java.util.SortedSet;
005    import java.util.TreeSet;
006    
007    import org.maltparser.core.exception.MaltChainedException;
008    import org.maltparser.core.syntaxgraph.GraphElement;
009    import org.maltparser.core.syntaxgraph.SyntaxGraphException;
010    import org.maltparser.core.syntaxgraph.edge.Edge;
011    
012    
013    
014    /**
015     * 
016     * 
017     * @author Johan Hall
018     *
019     */
020    public 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                            if (incomingEdges.last() != e) {
149                                    sb.append(",");
150                            }
151                    }
152                    sb.append("][O:");
153                    for (Edge e : outgoingEdges) {
154                            sb.append(e.getTarget().getIndex());
155                            if (outgoingEdges.last() != e) {
156                                    sb.append(",");
157                            }
158                    }
159                    sb.append("]");
160                    sb.append(super.toString());
161                    return sb.toString();
162            }
163    }