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                            System.out.println("The incoming edge's 'to' reference is not correct");
047                            return;
048                    }
049                    incomingEdges.remove(in);
050            }
051    
052            public void removeOutgoingEdge(Edge out) throws MaltChainedException {
053                    if (out.getSource() != this) {
054                            System.out.println("The outgoing edge's 'from' reference is not correct");
055                            return;
056                    }
057                    outgoingEdges.remove(out);
058            }
059    
060            public int getLeftmostProperDescendantIndex() throws MaltChainedException {
061                    ComparableNode node = getLeftmostProperDescendant();
062                    return (node != null)?node.getIndex():-1;
063            }
064            
065            public int getRightmostProperDescendantIndex() throws MaltChainedException {
066                    ComparableNode node = getRightmostProperDescendant();
067                    return (node != null)?node.getIndex():-1;
068            }
069            
070            public int getLeftmostDescendantIndex() throws MaltChainedException {
071                    ComparableNode node = getLeftmostProperDescendant();
072                    return (node != null)?node.getIndex():this.getIndex();
073            }
074            
075            public int getRightmostDescendantIndex() throws MaltChainedException {
076                    ComparableNode node = getRightmostProperDescendant();
077                    return (node != null)?node.getIndex():this.getIndex();
078            }
079            
080            public Iterator<Edge> getIncomingEdgeIterator() {
081                    return incomingEdges.iterator();
082            }
083            
084            public Iterator<Edge> getOutgoingEdgeIterator() {
085                    return outgoingEdges.iterator();
086            }
087            
088            public void clear() throws MaltChainedException {
089                    super.clear();
090                    incomingEdges.clear();
091                    outgoingEdges.clear();
092            }
093            
094            public int getInDegree() {
095                    return incomingEdges.size();
096            }
097            
098            public int getOutDegree() {
099                    return outgoingEdges.size();
100            }
101            
102            public SortedSet<Edge> getIncomingSecondaryEdges() {
103                    SortedSet<Edge> inSecEdges = new TreeSet<Edge>();
104                    for (Edge e : incomingEdges) {
105                            if (e.getType() == Edge.SECONDARY_EDGE) {
106                                    inSecEdges.add(e);
107                            }
108                    }
109                    return inSecEdges;
110            }
111            
112            public SortedSet<Edge> getOutgoingSecondaryEdges() {
113                    SortedSet<Edge> outSecEdges = new TreeSet<Edge>();
114                    for (Edge e : outgoingEdges) {
115                            if (e.getType() == Edge.SECONDARY_EDGE) {
116                                    outSecEdges.add(e);
117                            }
118                    }
119                    return outSecEdges;
120            }
121            
122            public int compareTo(ComparableNode o) {                
123                    return super.compareTo((GraphElement)o);
124            }
125            
126            public abstract int getIndex();
127            public abstract void setIndex(int index) throws MaltChainedException;
128            public abstract boolean isRoot();
129            
130            public boolean equals(Object obj) {
131                    GraphNode v = (GraphNode)obj;
132                    return super.equals(obj) && incomingEdges.equals(v.incomingEdges) 
133                                    && outgoingEdges.equals(v.outgoingEdges); 
134            }
135            
136            public int hashCode() {
137                    int hash = 7;
138                    hash = 31 * hash + super.hashCode();
139                    hash = 31 * hash + (null == incomingEdges ? 0 : incomingEdges.hashCode());
140                    hash = 31 * hash + (null == outgoingEdges ? 0 : outgoingEdges.hashCode());
141                    return hash;
142            }
143            
144            public String toString() {
145                    final StringBuilder sb = new StringBuilder();
146                    sb.append(getIndex());
147                    sb.append(" [I:");
148                    for (Edge e : incomingEdges) {
149                            sb.append(e.getSource().getIndex());
150                            if (incomingEdges.last() != e) {
151                                    sb.append(",");
152                            }
153                    }
154                    sb.append("][O:");
155                    for (Edge e : outgoingEdges) {
156                            sb.append(e.getTarget().getIndex());
157                            if (outgoingEdges.last() != e) {
158                                    sb.append(",");
159                            }
160                    }
161                    sb.append("]");
162                    sb.append(super.toString());
163                    return sb.toString();
164            }
165    }