| STreeNode.java |
1 /*
2 * STreeNode.java
3 *
4 * Copyright (c) 1998-2004, 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.13 2004/07/21 17:10:07 akshay Exp $
14 */
15
16 package gate.gui;
17
18 import java.util.*;
19
20 import javax.swing.tree.DefaultMutableTreeNode;
21
22 import gate.*;
23 import gate.util.InvalidOffsetException;
24 import gate.util.Out;
25
26
27 public class STreeNode extends DefaultMutableTreeNode {
28
29 /** Debug flag */
30 private static final boolean DEBUG = false;
31 private static final String ADDEDSET = "TreeViewerTempAdded";
32 private static final String REMOVEDSET = "TreeViewerTempRemoved";
33
34 static int nextID = 0;
35
36 int level; // level in the syntax tree
37 int nodeID; //ID of the node
38
39 long start, end; //the start and end nodes for this annotation
40 Annotation annot; //the annotation that's created during import/export
41 //not to be used otherwise. During import span is set to
42 //be the same as the annotation span. During export the
43 //annotation span is set to be the same as the span.
44
45 public STreeNode(Annotation annot) {
46 level = -1;
47 nodeID = nextID++;
48 //span = annot.getSpans().getElementAt(0);
49 //get the first span, there should be no others
50 this.annot = annot;
51 this.start = annot.getStartNode().getOffset().longValue();
52 this.end = annot.getEndNode().getOffset().longValue();
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 Long lStart = new Long(start), lEnd = new Long(end);
150 // try {
151 // attribs.put("text",
152 // doc.getContent().getContent(lStart, lEnd).toString());
153 // } catch (InvalidOffsetException ex) {
154 // throw new RuntimeException(ex.getMessage());
155 // }
156 attribs.put("text",
157 text.substring( (int) (start - utteranceOffset),
158 (int) (end - utteranceOffset) )
159 );
160 attribs.put("cat", (String) this.getUserObject());
161 attribs.put("consists", consists);
162
163 // children comes from DefaultMutableTreeNode
164 for (Iterator i = children.iterator(); i.hasNext(); ) {
165 STreeNode child = (STreeNode) i.next();
166 if (child.getAnnotation() == null) {
167 if (child.getAllowsChildren())
168 if (createAnnotation(doc, type, text, utteranceOffset))
169 consists.add(child.getAnnotation().getId());
170 } else
171 consists.add(child.getAnnotation().getId());
172 }
173
174 //!!! Need to account for the name of the Annot Set
175 AnnotationSet theSet = doc.getAnnotations(ADDEDSET);
176 try {
177 Integer Id = theSet.add(lStart, lEnd, type, attribs);
178 this.annot = theSet.get(Id);
179 created = true;
180 } catch (InvalidOffsetException ex) {
181 Out.println("Invalid annotation offsets: "
182 + start + " and/or " + end);
183 created = false;
184 }
185
186 return created;
187 }// public boolean createAnnotation
188
189
190 /**
191 * Transfers the annotations from added to the given annotation set
192 * Also, for each annotation in removed, removes it from the given annotation set
193 * Called by OkAction() in the treeViewer to finalise the changes.
194 */
195 public static boolean transferAnnotations(Document doc, AnnotationSet targetAS) {
196 if (doc == null || targetAS == null)
197 return false;
198
199 HashMap tempId2permId = new HashMap();
200 List newAnnots = new ArrayList();
201 AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
202 if (addedSet != null && !addedSet.isEmpty()) {
203 Iterator addedIter = addedSet.iterator();
204 while (addedIter.hasNext()) {
205 Annotation annot = (Annotation) addedIter.next();
206 try {
207 Integer permId =
208 targetAS.add(annot.getStartNode().getOffset(),
209 annot.getEndNode().getOffset(),
210 annot.getType(),
211 annot.getFeatures());
212 tempId2permId.put(annot.getId(), permId);
213 newAnnots.add(targetAS.get(permId));
214 } catch (InvalidOffsetException ex) {
215 Out.println("Invalid annotation offsets: "
216 + annot.getStartNode().getOffset()
217 + " and/or " + annot.getEndNode().getOffset());
218 }
219 }//while
220
221 //now update the consists Ids, because they have the old Ids in them
222 for (int i=0; i < newAnnots.size(); i++) {
223 Annotation newAnnot = (Annotation) newAnnots.get(i);
224 List children = (List) newAnnot.getFeatures().get(
225 SyntaxTreeViewer.NODE_CONSISTS_FEATURE_NAME);
226 if (children == null || children.size()== 0) {
227 continue;
228 }
229 else {
230 List newList = new ArrayList();
231 for (int k=0; k< children.size(); k++) {
232 Integer oldId = (Integer) children.get(k);
233 if (tempId2permId.get(oldId) != null)
234 newList.add(tempId2permId.get(oldId));
235 else
236 newList.add(oldId);
237 }
238 newAnnot.getFeatures().put(SyntaxTreeViewer.NODE_CONSISTS_FEATURE_NAME,
239 newList);
240 }
241 }//for
242
243 addedSet.clear();
244
245 }
246 doc.removeAnnotationSet(ADDEDSET);
247
248
249 AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
250 if (removedSet != null && ! removedSet.isEmpty()) {
251 targetAS.removeAll(removedSet);
252 removedSet.clear();
253 }
254 doc.removeAnnotationSet(REMOVEDSET);
255
256 return true;
257 }
258
259 public static void undo(Document doc) {
260 AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
261 AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
262 addedSet.clear();
263 removedSet.clear();
264 doc.removeAnnotationSet(ADDEDSET);
265 doc.removeAnnotationSet(REMOVEDSET);
266 }
267
268 /** Store the annotation in the deleted list so it can retrieved later */
269 public void removeAnnotation(Document doc) {
270 if (this.annot == null || doc == null)
271 return;
272
273 doc.getAnnotations(REMOVEDSET).add(this.annot);
274
275 this.annot = null;
276 }// public void removeAnnotation(Document doc)
277
278 } // STreeNode
279
280 // $Log: STreeNode.java,v $
281 // Revision 1.13 2004/07/21 17:10:07 akshay
282 // Changed copyright from 1998-2001 to 1998-2004
283 //
284 // Revision 1.12 2004/03/25 13:01:03 valyt
285 // Imports optimisation throughout the Java sources
286 // (to get rid of annoying warnings in Eclipse)
287 //
288 // Revision 1.11 2003/01/28 10:01:16 marin
289 // [marin] bugfixes from Kali
290 //
291 // Revision 1.10 2001/12/03 14:04:04 kalina
292 // code cleanup in STreeNode.java
293 //
294 // Revision 1.9 2001/08/07 19:03:05 kalina
295 // Made the tree viewer use Token annotations to break the sentence for annotation
296 //
297 // Revision 1.8 2001/08/07 17:01:32 kalina
298 // Changed the AVR implementing classes in line with the updated AVR
299 // API (cancelAction() and setSpan new parameter).
300 //
301 // Also updated the TreeViewer, so now it can be used to edit and view
302 // Sentence annotations and the SyntaxTreeNodes associated with them.
303 // So if you have trees, it'll show them, if not, it'll help you build them.
304 //
305 // Revision 1.7 2001/04/09 10:36:36 oana
306 // a few changes in the code style
307 //
308 // Revision 1.6 2000/11/08 16:35:00 hamish
309 // formatting
310 //
311 // Revision 1.5 2000/10/26 10:45:25 oana
312 // Modified in the code style
313 //
314 // Revision 1.4 2000/10/18 13:26:47 hamish
315 // Factory.createResource now working, with a utility method that uses
316 // reflection (via java.beans.Introspector) to set properties on a resource
317 // from the
318 // parameter list fed to createResource.
319 // resources may now have both an interface and a class; they are indexed
320 // by interface type; the class is used to instantiate them
321 // moved createResource from CR to Factory
322 // removed Transients; use Factory instead
323 //
324 // Revision 1.3 2000/10/16 16:44:32 oana
325 // Changed the comment of DEBUG variable
326 //
327 // Revision 1.2 2000/10/10 15:36:34 oana
328 // Changed System.out in Out and System.err in Err;
329 // Added the DEBUG variable seted on false;
330 // Added in the header the licence;
331 //
332 // Revision 1.1 2000/09/20 17:03:37 kalina
333 // Added the tree viewer from the prototype. It works now with the new
334 // annotation API.
335 //
336 // Revision 1.6 1999/08/23 14:13:38 kalina
337 // Fixed resizing bugs in tree viewers
338 //
339 // Revision 1.5 1999/08/20 21:11:56 kalina
340 // Fixed most bugs and TreeViewer can now import and export annotations
341 // correctly
342 // There is still a delete bug somewhere.
343 //
344 // Revision 1.4 1999/08/18 17:55:24 kalina
345 // Added annotation export for the TreeViewer. Annotation import is the only
346 // thing that remains.
347 //
348 // Revision 1.3 1999/08/13 17:56:31 kalina
349 // Fixed the annotation of nodes in the TreeViewer to be done with click
350 //
351 // Revision 1.2 1999/08/12 16:10:12 kalina
352 // Added a new tree stereotype. Not in final version but would do for testing.
353 //
354 // Improved the tree viewer to allow dynamic creation of all nodes.
355 // Now I can build many trees or one tree; can delete non-terminal nodes;
356 // select/unselect nodes for annotation
357 // Overlapping trees are not a big problem too :-) Not wonderfully drawn but
358 // would do.
359 //
360 // Revision 1.1 1999/08/09 18:00:53 kalina
361 // Made the tree viewer to display an utterance/sentence annotation to start annotating them
362 //
363