001    package org.maltparser.core.syntaxgraph;
002    
003    import java.util.Observable;
004    import java.util.Set;
005    
006    import org.maltparser.core.exception.MaltChainedException;
007    import org.maltparser.core.symbol.SymbolTable;
008    
009    /**
010    *
011    *
012    * @author Johan Hall
013    */
014    public abstract class GraphElement extends Observable implements Element {
015            private SyntaxGraph belongsToGraph;
016            private LabelSet labelSet;
017    
018            public GraphElement() {
019                    belongsToGraph = null;
020                    labelSet = null;
021            }
022            
023            /**
024             * Adds a label (a string value) to the symbol table and to the graph element. 
025             * 
026             * @param table the symbol table
027             * @param symbol a label symbol
028             * @throws MaltChainedException
029             */
030            public void addLabel(SymbolTable table, String symbol) throws MaltChainedException {
031                    table.addSymbol(symbol);
032                    addLabel(table, table.getSymbolStringToCode(symbol));
033            }
034            
035            /**
036             * Adds a label (an integer value) to the symbol table and to the graph element.
037             * 
038             * @param table the symbol table
039             * @param code a label code
040             * @throws MaltChainedException
041             */
042            public void addLabel(SymbolTable table, int code) throws MaltChainedException {
043                    if (table.getSymbolCodeToString(code) != null) {
044                            if (labelSet == null) {
045                                    if (belongsToGraph == null) {
046                                            throw new SyntaxGraphException("The graph element doesn't belong to any graph. ");
047                                    }
048                                    labelSet = belongsToGraph.checkOutNewLabelSet();
049                            }
050                            labelSet.put(table, code);
051                            setChanged(); 
052                            notifyObservers(table);
053                    }
054            }
055            
056            /**
057             * Adds the labels of the label set to the label set of the graph element.
058             * 
059             * @param labels a label set.
060             * @throws MaltChainedException
061             */
062            public void addLabel(LabelSet labels) throws MaltChainedException {
063                    if (labels != null) {
064                            for (SymbolTable table : labels.keySet()) {
065                                    addLabel(table, labels.get(table));
066                            }
067                    }
068            }
069            
070            /**
071             * Returns <i>true</i> if the graph element has a label for the symbol table, otherwise <i>false</i>.
072             * 
073             * @param table the symbol table
074             * @return <i>true</i> if the graph element has a label for the symbol table, otherwise <i>false</i>.
075             * @throws MaltChainedException
076             */
077            public boolean hasLabel(SymbolTable table) throws MaltChainedException {
078                    if (labelSet != null) {
079                            return labelSet.containsKey(table);
080                    }
081                    return false;
082            }
083            
084            /**
085             * Returns the label symbol(a string representation) of the symbol table if it exists, otherwise 
086             * an exception is thrown.
087             * 
088             * @param table the symbol table
089             * @return the label (a string representation) of the symbol table if it exists.
090             * @throws MaltChainedException
091             */
092            public String getLabelSymbol(SymbolTable table) throws MaltChainedException {
093                    Integer code = labelSet.get(table);
094                    if (code == null) {
095                            throw new SyntaxGraphException("No label symbol available for label '"+table.getName()+"'.");
096                    }
097                    return table.getSymbolCodeToString(code);
098            }
099            
100            /**
101             * Returns the label code (an integer representation) of the symbol table if it exists, otherwise 
102             * an exception is thrown.
103             * 
104             * @param table the symbol table
105             * @return the label code (an integer representation) of the symbol table if it exists
106             * @throws MaltChainedException
107             */
108            public int getLabelCode(SymbolTable table) throws MaltChainedException {
109                    Integer code = labelSet.get(table);
110                    if (code == null) {
111                            throw new SyntaxGraphException("No label symbol available for label '"+table.getName()+"'.");
112                    }
113    //              if (code != null) {
114    //                      return -1;
115    //              }
116                    return code.intValue();
117            }
118            
119            /**
120             * Returns <i>true</i> if the graph element has one or more labels, otherwise <i>false</i>.
121             * 
122             * @return <i>true</i> if the graph element has one or more labels, otherwise <i>false</i>.
123             */
124            public boolean isLabeled() {
125                    if (labelSet == null) {
126                            return false;
127                    }
128                    return labelSet.size() > 0;
129            }
130            
131            /**
132             * Returns the number of labels of the graph element.
133             * 
134             * @return the number of labels of the graph element.
135             */
136            public int nLabels() {
137                    if (labelSet == null) {
138                            return 0;
139                    }
140                    return labelSet.size();
141            }
142            
143            /**
144             * Returns a set of symbol tables (labeling functions or label types) that labels the graph element.
145             * 
146             * @return a set of symbol tables (labeling functions or label types)
147             */
148            public Set<SymbolTable> getLabelTypes() {
149                    if (labelSet == null) {
150                            return null;
151                    }
152                    return labelSet.keySet();
153            }
154            
155            /**
156             * Returns the label set.
157             * 
158             * @return the label set.
159             */
160            public LabelSet getLabelSet() {
161                    return labelSet;
162            }
163            
164            public void removeLabel(SymbolTable table) throws MaltChainedException {
165                    if (labelSet != null) {
166                            labelSet.remove(table);
167                    }
168            }
169            
170            public void removeLabels() throws MaltChainedException {
171                    if (labelSet != null && belongsToGraph != null) {
172                            belongsToGraph.checkInLabelSet(labelSet);
173                    }
174                    labelSet = null;
175            }
176            
177            /**
178             * Returns the graph (structure) in which the graph element belongs to. 
179             * 
180             * @return the graph (structure) in which the graph element belongs to. 
181             */
182            public SyntaxGraph getBelongsToGraph() {
183                    return belongsToGraph;
184            }
185            
186            /**
187             * Sets the graph (structure) in which the graph element belongs to. 
188             * 
189             * @param belongsToGraph a graph (structure).
190             */
191            public void setBelongsToGraph(SyntaxGraph belongsToGraph) {
192                    this.belongsToGraph = belongsToGraph;
193                    addObserver(belongsToGraph);
194            }
195            
196    
197            /**
198             * Resets the graph element.
199             * 
200             * @throws MaltChainedException
201             */
202            public void clear() throws MaltChainedException {
203                    if (labelSet != null && belongsToGraph != null) {
204                            belongsToGraph.checkInLabelSet(labelSet);
205                    }
206                    labelSet = null;
207                    deleteObserver(belongsToGraph);
208                    belongsToGraph = null;
209            }
210            
211            public boolean equals(Object obj) {
212                    GraphElement ge = (GraphElement)obj;
213                    return belongsToGraph == ge.getBelongsToGraph() && labelSet == null ? ge.getLabelSet() == null : labelSet.equals(ge.getLabelSet()); 
214            }
215            
216            public int hashCode() {
217                    int hash = 7;
218                    hash = 31 * hash + (null == belongsToGraph ? 0 : belongsToGraph.hashCode());
219                    return 31 * hash + (null == labelSet ? 0 : labelSet.hashCode());
220            }
221            
222            public int compareTo(GraphElement o) {
223                    final int BEFORE = -1;
224                final int EQUAL = 0;
225                final int AFTER = 1;
226                if ( this == o ) return EQUAL;
227                    
228                if (this.labelSet == null && o.labelSet != null) return BEFORE;
229                if (this.labelSet != null && o.labelSet == null) return AFTER;
230                if (this.labelSet == null && o.labelSet == null) return EQUAL;
231                
232                int comparison = EQUAL;
233                    for (SymbolTable table : labelSet.keySet()) {
234                            Integer ocode = o.labelSet.get(table);
235                            Integer tcode = labelSet.get(table);
236                            if (ocode != null && tcode != null) {
237                                    if (!ocode.equals(tcode)) {
238                                            try {
239                                                    comparison = table.getSymbolCodeToString(tcode).compareTo(table.getSymbolCodeToString(ocode));
240                                                    if ( comparison != EQUAL ) return comparison;
241                                            } catch (MaltChainedException e) { }
242                                    }
243                            }
244                    }
245                    return EQUAL;
246            }
247            
248            public String toString() {
249                    final StringBuilder sb = new StringBuilder();
250                    if (labelSet != null) {
251                            for (SymbolTable table : labelSet.keySet()) {
252                                    try {
253                                            sb.append(table.getName());
254                                            sb.append(':');
255                                            sb.append(getLabelSymbol(table));
256                                    } catch (MaltChainedException e) {
257                                            System.err.println("Print error : "+e.getMessageChain());
258                                    }
259                                    sb.append(' ');
260                            }
261                    }
262                    return sb.toString();
263            }
264    }