001 /*
002 * STreeNode.java
003 *
004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006 *
007 * This file is part of GATE (see http://gate.ac.uk/), and is free
008 * software, licenced under the GNU Library General Public License,
009 * Version 2, June 1991 (in the distribution as file licence.html,
010 * and also available at http://gate.ac.uk/gate/licence.html).
011 *
012 * Kalina Bontcheva, 07/08/2001
013 *
014 * $Id: STreeNode.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015 */
016
017 package gate.gui;
018
019 import java.util.*;
020
021 import javax.swing.tree.DefaultMutableTreeNode;
022
023 import gate.*;
024 import gate.util.InvalidOffsetException;
025 import gate.util.Out;
026
027
028 public class STreeNode extends DefaultMutableTreeNode {
029
030 /** Debug flag */
031 private static final boolean DEBUG = false;
032 private static final String ADDEDSET = "TreeViewerTempAdded";
033 private static final String REMOVEDSET = "TreeViewerTempRemoved";
034
035 static int nextID = 0;
036
037 int level; // level in the syntax tree
038 int nodeID; //ID of the node
039
040 long start, end; //the start and end nodes for this annotation
041 Annotation annot; //the annotation that's created during import/export
042 //not to be used otherwise. During import span is set to
043 //be the same as the annotation span. During export the
044 //annotation span is set to be the same as the span.
045
046 public STreeNode(Annotation annot) {
047 level = -1;
048 nodeID = nextID++;
049 //span = annot.getSpans().getElementAt(0);
050 //get the first span, there should be no others
051 this.annot = annot;
052 this.start = annot.getStartNode().getOffset().longValue();
053 this.end = annot.getEndNode().getOffset().longValue();
054 }// public STreeNode(Annotation annot)
055
056 public STreeNode(long start, long end) {
057 level = -1;
058 nodeID = nextID++;
059 this.start = start;
060 this.end = end;
061 }// public STreeNode(int start, int end)
062
063 public STreeNode() {
064 level = -1;
065 nodeID = nextID++;
066 start = 0;
067 end = 0;
068 }// public STreeNode()
069
070 public int getLevel() {
071 return level;
072 }// public int getLevel()
073
074 public void setLevel(long level) {
075 this.level = (int) level;
076 }// public void setLevel(int level)
077
078 public void setLevel(int level) {
079 this.level = level;
080 }// public void setLevel(int level)
081
082 public int getID() {
083 return nodeID;
084 }// public int getID()
085
086 public long getStart() {
087 return start;
088 }// public int getStart()
089
090 public void setStart(long start) {
091 this.start = start;
092 }// public void setStart(int start)
093
094 public long getEnd() {
095 return end;
096 }// public int getEnd()
097
098 public void setEnd(long end) {
099 this.end = end;
100 }// public void setEnd(int end)
101
102 /**
103 * This also sets the span to match the annotation span!
104 */
105 public void setAnnotation(Annotation annot) {
106 this.annot = annot;
107 this.start = annot.getStartNode().getOffset().longValue();
108 this.end = annot.getEndNode().getOffset().longValue();
109 }// public void setAnnotation(Annotation annot)
110
111 public Annotation getAnnotation() {
112 return annot;
113 }// public Annotation getAnnotation()
114
115 public void disconnectChildren() {
116 for (Iterator i = this.children.iterator(); i.hasNext(); )
117 ((STreeNode) i.next()).setParent(null);
118 this.children.clear();
119 }// public void disconnectChildren()
120
121 /**
122 * Creates an annotation of the given type. If the children don't have their
123 * annotation objects created, it creates them and assigns the pointers.
124 * Expects the text string relative to which all offsets were created!
125 */
126 public boolean createAnnotation(Document doc, String type,
127 String text, long utteranceOffset) {
128 boolean created = false;
129
130 if (annot != null )
131 return false;
132
133 //no document, so cannot add annotations
134 if (doc == null)
135 return false;
136
137 // check if it has children. If it hasn't then it shouldn't have an
138 // annotation because all our leaf nodes are actually just words
139 // from the text (e.g. "this", "that"). Their categories are always
140 // encoded as non-terminal nodes.
141 if ( ! this.getAllowsChildren())
142 return false;
143
144 FeatureMap attribs = Factory.newFeatureMap();
145 // the text spanned by the annotation is stored as the userObject of the
146 // tree node
147 // comes from the default Swing tree node
148 List consists = new ArrayList();
149
150 Long lStart = new Long(start), lEnd = new Long(end);
151 // try {
152 // attribs.put("text",
153 // doc.getContent().getContent(lStart, lEnd).toString());
154 // } catch (InvalidOffsetException ex) {
155 // throw new RuntimeException(ex.getMessage());
156 // }
157 attribs.put("text",
158 text.substring( (int) (start - utteranceOffset),
159 (int) (end - utteranceOffset) )
160 );
161 attribs.put("cat", (String) this.getUserObject());
162 attribs.put("consists", consists);
163
164 // children comes from DefaultMutableTreeNode
165 for (Iterator i = children.iterator(); i.hasNext(); ) {
166 STreeNode child = (STreeNode) i.next();
167 if (child.getAnnotation() == null) {
168 if (child.getAllowsChildren())
169 if (createAnnotation(doc, type, text, utteranceOffset))
170 consists.add(child.getAnnotation().getId());
171 } else
172 consists.add(child.getAnnotation().getId());
173 }
174
175 //!!! Need to account for the name of the Annot Set
176 AnnotationSet theSet = doc.getAnnotations(ADDEDSET);
177 try {
178 Integer Id = theSet.add(lStart, lEnd, type, attribs);
179 this.annot = theSet.get(Id);
180 created = true;
181 } catch (InvalidOffsetException ex) {
182 Out.println("Invalid annotation offsets: "
183 + start + " and/or " + end);
184 created = false;
185 }
186
187 return created;
188 }// public boolean createAnnotation
189
190
191 /**
192 * Transfers the annotations from added to the given annotation set
193 * Also, for each annotation in removed, removes it from the given annotation set
194 * Called by OkAction() in the treeViewer to finalise the changes.
195 */
196 public static boolean transferAnnotations(Document doc, AnnotationSet targetAS) {
197 if (doc == null || targetAS == null)
198 return false;
199
200 HashMap tempId2permId = new HashMap();
201 List newAnnots = new ArrayList();
202 AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
203 if (addedSet != null && !addedSet.isEmpty()) {
204 Iterator addedIter = addedSet.iterator();
205 while (addedIter.hasNext()) {
206 Annotation annot = (Annotation) addedIter.next();
207 try {
208 Integer permId =
209 targetAS.add(annot.getStartNode().getOffset(),
210 annot.getEndNode().getOffset(),
211 annot.getType(),
212 annot.getFeatures());
213 tempId2permId.put(annot.getId(), permId);
214 newAnnots.add(targetAS.get(permId));
215 } catch (InvalidOffsetException ex) {
216 Out.println("Invalid annotation offsets: "
217 + annot.getStartNode().getOffset()
218 + " and/or " + annot.getEndNode().getOffset());
219 }
220 }//while
221
222 //now update the consists Ids, because they have the old Ids in them
223 for (int i=0; i < newAnnots.size(); i++) {
224 Annotation newAnnot = (Annotation) newAnnots.get(i);
225 List children = (List) newAnnot.getFeatures().get(
226 SyntaxTreeViewer.NODE_CONSISTS_FEATURE_NAME);
227 if (children == null || children.size()== 0) {
228 continue;
229 }
230 else {
231 List newList = new ArrayList();
232 for (int k=0; k< children.size(); k++) {
233 Integer oldId = (Integer) children.get(k);
234 if (tempId2permId.get(oldId) != null)
235 newList.add(tempId2permId.get(oldId));
236 else
237 newList.add(oldId);
238 }
239 newAnnot.getFeatures().put(SyntaxTreeViewer.NODE_CONSISTS_FEATURE_NAME,
240 newList);
241 }
242 }//for
243
244 addedSet.clear();
245
246 }
247 doc.removeAnnotationSet(ADDEDSET);
248
249
250 AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
251 if (removedSet != null && ! removedSet.isEmpty()) {
252 targetAS.removeAll(removedSet);
253 removedSet.clear();
254 }
255 doc.removeAnnotationSet(REMOVEDSET);
256
257 return true;
258 }
259
260 public static void undo(Document doc) {
261 AnnotationSet addedSet = doc.getAnnotations(ADDEDSET);
262 AnnotationSet removedSet = doc.getAnnotations(REMOVEDSET);
263 addedSet.clear();
264 removedSet.clear();
265 doc.removeAnnotationSet(ADDEDSET);
266 doc.removeAnnotationSet(REMOVEDSET);
267 }
268
269 /** Store the annotation in the deleted list so it can retrieved later */
270 public void removeAnnotation(Document doc) {
271 if (this.annot == null || doc == null)
272 return;
273
274 doc.getAnnotations(REMOVEDSET).add(this.annot);
275
276 this.annot = null;
277 }// public void removeAnnotation(Document doc)
278
279 } // STreeNode
280
281 // $Log$
282 // Revision 1.14 2005/01/11 13:51:34 ian
283 // Updating copyrights to 1998-2005 in preparation for v3.0
284 //
285 // Revision 1.13 2004/07/21 17:10:07 akshay
286 // Changed copyright from 1998-2001 to 1998-2005
287 //
288 // Revision 1.12 2004/03/25 13:01:03 valyt
289 // Imports optimisation throughout the Java sources
290 // (to get rid of annoying warnings in Eclipse)
291 //
292 // Revision 1.11 2003/01/28 10:01:16 marin
293 // [marin] bugfixes from Kali
294 //
295 // Revision 1.10 2001/12/03 14:04:04 kalina
296 // code cleanup in STreeNode.java
297 //
298 // Revision 1.9 2001/08/07 19:03:05 kalina
299 // Made the tree viewer use Token annotations to break the sentence for annotation
300 //
301 // Revision 1.8 2001/08/07 17:01:32 kalina
302 // Changed the AVR implementing classes in line with the updated AVR
303 // API (cancelAction() and setSpan new parameter).
304 //
305 // Also updated the TreeViewer, so now it can be used to edit and view
306 // Sentence annotations and the SyntaxTreeNodes associated with them.
307 // So if you have trees, it'll show them, if not, it'll help you build them.
308 //
309 // Revision 1.7 2001/04/09 10:36:36 oana
310 // a few changes in the code style
311 //
312 // Revision 1.6 2000/11/08 16:35:00 hamish
313 // formatting
314 //
315 // Revision 1.5 2000/10/26 10:45:25 oana
316 // Modified in the code style
317 //
318 // Revision 1.4 2000/10/18 13:26:47 hamish
319 // Factory.createResource now working, with a utility method that uses
320 // reflection (via java.beans.Introspector) to set properties on a resource
321 // from the
322 // parameter list fed to createResource.
323 // resources may now have both an interface and a class; they are indexed
324 // by interface type; the class is used to instantiate them
325 // moved createResource from CR to Factory
326 // removed Transients; use Factory instead
327 //
328 // Revision 1.3 2000/10/16 16:44:32 oana
329 // Changed the comment of DEBUG variable
330 //
331 // Revision 1.2 2000/10/10 15:36:34 oana
332 // Changed System.out in Out and System.err in Err;
333 // Added the DEBUG variable seted on false;
334 // Added in the header the licence;
335 //
336 // Revision 1.1 2000/09/20 17:03:37 kalina
337 // Added the tree viewer from the prototype. It works now with the new
338 // annotation API.
339 //
340 // Revision 1.6 1999/08/23 14:13:38 kalina
341 // Fixed resizing bugs in tree viewers
342 //
343 // Revision 1.5 1999/08/20 21:11:56 kalina
344 // Fixed most bugs and TreeViewer can now import and export annotations
345 // correctly
346 // There is still a delete bug somewhere.
347 //
348 // Revision 1.4 1999/08/18 17:55:24 kalina
349 // Added annotation export for the TreeViewer. Annotation import is the only
350 // thing that remains.
351 //
352 // Revision 1.3 1999/08/13 17:56:31 kalina
353 // Fixed the annotation of nodes in the TreeViewer to be done with click
354 //
355 // Revision 1.2 1999/08/12 16:10:12 kalina
356 // Added a new tree stereotype. Not in final version but would do for testing.
357 //
358 // Improved the tree viewer to allow dynamic creation of all nodes.
359 // Now I can build many trees or one tree; can delete non-terminal nodes;
360 // select/unselect nodes for annotation
361 // Overlapping trees are not a big problem too :-) Not wonderfully drawn but
362 // would do.
363 //
364 // Revision 1.1 1999/08/09 18:00:53 kalina
365 // Made the tree viewer to display an utterance/sentence annotation to start annotating them
366 //
|