1   /*
2    *  STreeNode.java
3    *
4    *  Copyright (c) 1998-2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Kalina Bontcheva, 07/08/2001
12   *
13   *  $Id: STreeNode.java,v 1.10 2001/12/03 14:04:04 kalina Exp $
14   */
15  
16  package gate.gui;
17  
18  import javax.swing.tree.*;
19  
20  import java.awt.Rectangle;
21  
22  import java.util.*;
23  
24  
25  import gate.*;
26  import gate.util.*;
27  
28  
29  public class STreeNode extends DefaultMutableTreeNode {
30  
31    /** Debug flag */
32    private static final boolean DEBUG = false;
33    private static final String ADDEDSET = "TreeViewerTempAdded";
34    private static final String REMOVEDSET = "TreeViewerTempRemoved";
35  
36    static int nextID = 0;
37  
38    int level;            // level in the syntax tree
39    int nodeID;           //ID of the node
40  
41    long start, end;       //the start and end nodes for this annotation
42    Annotation annot;     //the annotation that's created during import/export
43                          //not to be used otherwise. During import span is set to
44                          //be the same as the annotation span. During export the
45                          //annotation span is set to be the same as the span.
46  
47    public STreeNode(Annotation annot) {
48      level = -1;
49      nodeID = nextID++;
50      //span = annot.getSpans().getElementAt(0);
51      //get the first span, there should be no others
52      this.annot = annot;
53    }// public STreeNode(Annotation annot)
54  
55    public STreeNode(long start, long end) {
56      level = -1;
57      nodeID = nextID++;
58      this.start = start;
59      this.end = end;
60    }// public STreeNode(int start, int end)
61  
62    public STreeNode() {
63      level = -1;
64      nodeID = nextID++;
65      start = 0;
66      end = 0;
67    }// public STreeNode()
68  
69    public int getLevel() {
70      return level;
71    }// public int getLevel()
72  
73    public void setLevel(long level) {
74      this.level = (int) level;
75    }// public void setLevel(int level)
76  
77    public void setLevel(int level) {
78      this.level = level;
79    }// public void setLevel(int level)
80  
81    public int getID() {
82      return nodeID;
83    }// public int getID()
84  
85    public long getStart() {
86      return start;
87    }// public int getStart()
88  
89    public void setStart(long start) {
90      this.start = start;
91    }// public void setStart(int start)
92  
93    public long getEnd() {
94      return end;
95    }// public int getEnd()
96  
97    public void setEnd(long end) {
98      this.end = end;
99    }// public void setEnd(int end)
100 
101   /**
102     * This also sets the span to match the annotation span!
103     */
104   public void setAnnotation(Annotation annot) {
105     this.annot = annot;
106     this.start = annot.getStartNode().getOffset().longValue();
107     this.end = annot.getEndNode().getOffset().longValue();
108   }// public void setAnnotation(Annotation annot)
109 
110   public Annotation getAnnotation() {
111     return annot;
112   }// public Annotation getAnnotation()
113 
114   public void disconnectChildren() {
115     for (Iterator i = this.children.iterator(); i.hasNext(); )
116       ((STreeNode) i.next()).setParent(null);
117     this.children.clear();
118   }// public void disconnectChildren()
119 
120   /**
121     * Creates an annotation of the given type. If the children don't have their
122     * annotation objects created, it creates them and assigns the pointers.
123     * Expects the text string relative to which all offsets were created!
124     */
125   public boolean createAnnotation(Document doc, String type,
126                                     String text, long utteranceOffset) {
127     boolean created = false;
128 
129     if (annot != null )
130       return false;
131 
132     //no document, so cannot add annotations
133     if (doc == null)
134       return false;
135 
136     // check if it has children. If it hasn't then it shouldn't have an
137     // annotation because all our leaf nodes are actually just words
138     // from the text (e.g. "this", "that"). Their categories are always
139     // encoded as non-terminal nodes.
140     if ( ! this.getAllowsChildren())
141       return false;
142 
143     FeatureMap attribs = Factory.newFeatureMap();
144     // the text spanned by the annotation is stored as the userObject of the
145     // tree node
146     // comes from the default Swing tree node
147     List consists = new ArrayList();
148 
149     attribs.put("text",
150                   text.substring( (int) (start - utteranceOffset),
151                                  (int) (end - utteranceOffset) )
152     );
153     attribs.put("cat", (String) this.getUserObject());
154     attribs.put("consists", consists);
155 
156     // children comes from DefaultMutableTreeNode
157     for (Iterator i = children.iterator(); i.hasNext(); ) {
158       STreeNode child = (STreeNode) i.next();
159       if (child.getAnnotation() == null) {
160         if (child.getAllowsChildren())
161           if (createAnnotation(doc, type, text, utteranceOffset))
162             consists.add(child.getAnnotation().getId());
163       } else
164         consists.add(child.getAnnotation().getId());
165     }
166 
167     //!!! Need to account for the name of the Annot Set
168     AnnotationSet theSet = doc.getAnnotations(ADDEDSET);
169     try {
170       Integer Id = theSet.add(new Long(start), new Long(end), type, attribs);
171       this.annot = theSet.get(Id);
172       created = true;
173     } catch (InvalidOffsetException ex) {
174       Out.println("Invalid annotation offsets: "
175                             + start + " and/or " + end);
176       created = false;
177     }
178 
179     return created;
180   }// public boolean createAnnotation
181 
182 
183   /**
184     * Transfers the annotations from added to the given annotation set
185     * Also, for each annotation in removed, removes it from the given annotation set
186     * Called by OkAction() in the treeViewer to finalise the changes.
187     */
188   public static boolean transferAnnotations(Document doc, AnnotationSet targetAS) {
189     if (doc == null || targetAS == null)
190       return false;
191 
192     AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
193     if (addedSet != null && !addedSet.isEmpty()) {
194       targetAS.addAll(addedSet);
195       addedSet.clear();
196     }
197     doc.removeAnnotationSet(ADDEDSET);
198 
199     AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
200     if (removedSet != null &&  ! removedSet.isEmpty()) {
201       targetAS.removeAll(removedSet);
202       removedSet.clear();
203     }
204     doc.removeAnnotationSet(REMOVEDSET);
205 
206     return true;
207   }
208 
209   public static void undo(Document doc) {
210     AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
211     AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
212     addedSet.clear();
213     removedSet.clear();
214     doc.removeAnnotationSet(ADDEDSET);
215     doc.removeAnnotationSet(REMOVEDSET);
216   }
217 
218   /** Store the annotation in the deleted list so it can retrieved later */
219   public void removeAnnotation(Document doc) {
220     if (this.annot == null || doc == null)
221       return;
222 
223     doc.getAnnotations(REMOVEDSET).add(this.annot);
224 
225     this.annot = null;
226   }//  public void removeAnnotation(Document doc)
227 
228 } // STreeNode
229 
230 // $Log: STreeNode.java,v $
231 // Revision 1.10  2001/12/03 14:04:04  kalina
232 // code cleanup in STreeNode.java
233 //
234 // Revision 1.9  2001/08/07 19:03:05  kalina
235 // Made the tree viewer use Token annotations to break the sentence for annotation
236 //
237 // Revision 1.8  2001/08/07 17:01:32  kalina
238 // Changed the AVR implementing classes in line with the updated AVR
239 // API (cancelAction() and setSpan new parameter).
240 //
241 // Also updated the TreeViewer, so now it can be used to edit and view
242 // Sentence annotations and the SyntaxTreeNodes associated with them.
243 // So if you have trees, it'll show them, if not, it'll help you build them.
244 //
245 // Revision 1.7  2001/04/09 10:36:36  oana
246 // a few changes in the code style
247 //
248 // Revision 1.6  2000/11/08 16:35:00  hamish
249 // formatting
250 //
251 // Revision 1.5  2000/10/26 10:45:25  oana
252 // Modified in the code style
253 //
254 // Revision 1.4  2000/10/18 13:26:47  hamish
255 // Factory.createResource now working, with a utility method that uses
256 // reflection (via java.beans.Introspector) to set properties on a resource
257 // from the
258 //     parameter list fed to createResource.
259 //     resources may now have both an interface and a class; they are indexed
260 //        by interface type; the class is used to instantiate them
261 //     moved createResource from CR to Factory
262 //     removed Transients; use Factory instead
263 //
264 // Revision 1.3  2000/10/16 16:44:32  oana
265 // Changed the comment of DEBUG variable
266 //
267 // Revision 1.2  2000/10/10 15:36:34  oana
268 // Changed System.out in Out and System.err in Err;
269 // Added the DEBUG variable seted on false;
270 // Added in the header the licence;
271 //
272 // Revision 1.1  2000/09/20 17:03:37  kalina
273 // Added the tree viewer from the prototype. It works now with the new
274 // annotation API.
275 //
276 // Revision 1.6  1999/08/23 14:13:38  kalina
277 // Fixed resizing bugs in tree viewers
278 //
279 // Revision 1.5  1999/08/20 21:11:56  kalina
280 // Fixed most bugs and TreeViewer can now import and export annotations
281 // correctly
282 // There is still a delete bug somewhere.
283 //
284 // Revision 1.4  1999/08/18 17:55:24  kalina
285 // Added annotation export for the TreeViewer. Annotation import is the only
286 // thing that remains.
287 //
288 // Revision 1.3  1999/08/13 17:56:31  kalina
289 // Fixed the annotation of nodes in the TreeViewer to be done with click
290 //
291 // Revision 1.2  1999/08/12 16:10:12  kalina
292 // Added a new tree stereotype. Not in final version but would do for testing.
293 //
294 // Improved the tree viewer to allow dynamic creation of all nodes.
295 // Now I can build many trees or one tree; can delete non-terminal nodes;
296 // select/unselect nodes for annotation
297 // Overlapping trees are not a big problem too :-) Not wonderfully drawn but
298 // would do.
299 //
300 // Revision 1.1  1999/08/09 18:00:53  kalina
301 // Made the tree viewer to display an utterance/sentence annotation to start annotating them
302 //
303