1
15
16 package gate.annotation;
17
18 import java.io.Serializable;
19 import java.util.Set;
20 import java.util.Vector;
21
22 import gate.*;
23 import gate.event.AnnotationEvent;
24 import gate.event.AnnotationListener;
25 import gate.util.AbstractFeatureBearer;
26 import gate.util.FeatureBearer;
27
28
31 public class AnnotationImpl extends AbstractFeatureBearer
32 implements Annotation, FeatureBearer, Comparable {
33
34
36 private static final boolean DEBUG = false;
37
38 static final long serialVersionUID = -5658993256574857725L;
39
40
49 protected AnnotationImpl(
50 Integer id, Node start, Node end, String type, FeatureMap features
51 ) {
52 this.id = id;
53 this.start = start;
54 this.end = end;
55 this.type = type;
56 this.features = features;
57
58 }
60
62 public Integer getId() {
63 return id;
64 }
66
68 public String getType() {
69 return type;
70 }
72
74 public Node getStartNode() {
75 return start;
76 }
78
80 public Node getEndNode() {
81 return end;
82 }
84
86 public String toString() {
87 return "AnnotationImpl: id=" + id + "; type=" + type +
88 "; features=" + features + "; start=" + start +
89 "; end=" + end + System.getProperty("line.separator");
90 }
92
94 public int compareTo(Object o) throws ClassCastException {
95 Annotation other = (Annotation) o;
96 return id.compareTo(other.getId());
97 }
99
104
105 public int hashCode(){
106 int hashCodeRes = 0;
107 if (start != null && start.getOffset() != null)
108 hashCodeRes ^= start.getOffset().hashCode();
109 if (end != null && end.getOffset() != null)
110 hashCodeRes ^= end.getOffset().hashCode();
111 if(features != null)
112 hashCodeRes ^= features.hashCode();
113 return hashCodeRes;
114 }
116
120 public boolean equals(Object obj){
121 if(obj == null)
122 return false;
123 Annotation other;
124 if(obj instanceof AnnotationImpl){
125 other = (Annotation) obj;
126 }else return false;
127
128 if((type == null) ^ (other.getType() == null))
130 return false;
131 if(type != null && (!type.equals(other.getType())))
132 return false;
133
134 if((id == null) ^ (other.getId() == null))
136 return false;
137 if((id != null )&& (!id.equals(other.getId())))
138 return false;
139
140 if((start == null) ^ (other.getStartNode() == null))
142 return false;
143 if(start != null){
144 if((start.getOffset() == null) ^
145 (other.getStartNode().getOffset() == null))
146 return false;
147 if(start.getOffset() != null &&
148 (!start.getOffset().equals(other.getStartNode().getOffset())))
149 return false;
150 }
151
152 if((end == null) ^ (other.getEndNode() == null))
154 return false;
155 if(end != null){
156 if((end.getOffset() == null) ^
157 (other.getEndNode().getOffset() == null))
158 return false;
159 if(end.getOffset() != null &&
160 (!end.getOffset().equals(other.getEndNode().getOffset())))
161 return false;
162 }
163
164 if((features == null) ^ (other.getFeatures() == null))
166 return false;
167 if(features != null && (!features.equals(other.getFeatures())))
168 return false;
169 return true;
170 }
172
175 public void setFeatures(FeatureMap features) {
176 if (eventHandler != null)
178 this.features.removeFeatureMapListener(eventHandler);
179
180 this.features = features;
181
182 if (annotationListeners != null && ! annotationListeners.isEmpty())
185 this.features.addFeatureMapListener(eventHandler);
186
187 fireAnnotationUpdated(new AnnotationEvent(
189 this,
190 AnnotationEvent.FEATURES_UPDATED));
191
192
193 }
194
195
196
204 public boolean isCompatible(Annotation anAnnot){
205 if (anAnnot == null) return false;
206 if (coextensive(anAnnot)){
207 if (anAnnot.getFeatures() == null) return true;
208 if (anAnnot.getFeatures().subsumes(this.getFeatures()))
209 return true;
210 } return false;
212 }
214
227 public boolean isCompatible(Annotation anAnnot, Set aFeatureNamesSet){
228 if (aFeatureNamesSet == null) return isCompatible(anAnnot);
230 if (anAnnot == null) return false;
231 if (coextensive(anAnnot)){
232 if (anAnnot.getFeatures() == null) return true;
233 if (anAnnot.getFeatures().subsumes(this.getFeatures(),aFeatureNamesSet))
234 return true;
235 } return false;
237 }
239
246 public boolean isPartiallyCompatible(Annotation anAnnot){
247 if (anAnnot == null) return false;
248 if (overlaps(anAnnot)){
249 if (anAnnot.getFeatures() == null) return true;
250 if (anAnnot.getFeatures().subsumes(this.getFeatures()))
251 return true;
252 } return false;
254 }
256
270 public boolean isPartiallyCompatible(Annotation anAnnot,Set aFeatureNamesSet){
271 if (aFeatureNamesSet == null) return isPartiallyCompatible(anAnnot);
272 if (anAnnot == null) return false;
273 if (overlaps(anAnnot)){
274 if (anAnnot.getFeatures() == null) return true;
275 if (anAnnot.getFeatures().subsumes(this.getFeatures(),aFeatureNamesSet))
276 return true;
277 } return false;
279 }
281
288 public boolean coextensive(Annotation anAnnot){
289 if((anAnnot.getStartNode() == null) ^ (this.getStartNode() == null))
291 return false;
292
293 if(anAnnot.getStartNode() != null){
294 if((anAnnot.getStartNode().getOffset() == null) ^
295 (this.getStartNode().getOffset() == null))
296 return false;
297 if(anAnnot.getStartNode().getOffset() != null &&
298 (!anAnnot.getStartNode().getOffset().equals(
299 this.getStartNode().getOffset())))
300 return false;
301 }
303 if((anAnnot.getEndNode() == null) ^ (this.getEndNode() == null))
305 return false;
306
307 if(anAnnot.getEndNode() != null){
308 if((anAnnot.getEndNode().getOffset() == null) ^
309 (this.getEndNode().getOffset() == null))
310 return false;
311 if(anAnnot.getEndNode().getOffset() != null &&
312 (!anAnnot.getEndNode().getOffset().equals(
313 this.getEndNode().getOffset())))
314 return false;
315 }
317 return true;
319 }
321
326 public boolean overlaps(Annotation aAnnot){
327 if (aAnnot == null) return false;
328 if (aAnnot.getStartNode() == null ||
329 aAnnot.getEndNode() == null ||
330 aAnnot.getStartNode().getOffset() == null ||
331 aAnnot.getEndNode().getOffset() == null) return false;
332
333
341
342 if ( aAnnot.getEndNode().getOffset().longValue() <=
343 this.getStartNode().getOffset().longValue())
344 return false;
345
346 if ( aAnnot.getStartNode().getOffset().longValue() >=
347 this.getEndNode().getOffset().longValue())
348 return false;
349
350 return true;
351 }
353
357
365 private transient Vector annotationListeners;
366
369 protected EventsHandler eventHandler;
370
371
372
376 public synchronized void removeAnnotationListener(AnnotationListener l) {
377 if (annotationListeners != null && annotationListeners.contains(l)) {
378 Vector v = (Vector) annotationListeners.clone();
379 v.removeElement(l);
380 annotationListeners = v;
381 }
382 }
383
387 public synchronized void addAnnotationListener(AnnotationListener l) {
388 Vector v = annotationListeners == null ? new Vector(2) : (Vector) annotationListeners.clone();
389
390 if (v.isEmpty()) {
394 FeatureMap features = getFeatures();
395 if (eventHandler == null)
396 eventHandler = new EventsHandler();
397 features.addFeatureMapListener(eventHandler);
398 }
399
400 if (!v.contains(l)) {
401 v.addElement(l);
402 annotationListeners = v;
403 }
404 }
405
409 protected void fireAnnotationUpdated(AnnotationEvent e) {
410 if (annotationListeners != null) {
411 Vector listeners = annotationListeners;
412 int count = listeners.size();
413 for (int i = 0; i < count; i++) {
414 ((AnnotationListener) listeners.elementAt(i)).annotationUpdated(e);
415 }
416 }
417 }
419
420
424 Integer id;
425
429 String type;
430
434
435
438 protected Node start;
439
440
443 protected Node end;
444
445
446
447
448
452 class EventsHandler implements gate.event.FeatureMapListener, Serializable {
453 public void featureMapUpdated(){
454 fireAnnotationUpdated(new AnnotationEvent(
456 AnnotationImpl.this,
457 AnnotationEvent.FEATURES_UPDATED));
458 }
459 static final long serialVersionUID = 2608156420244752907L;
460
461 }
463
464 }