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 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
61
63 public Integer getId() {
64 return id;
65 }
67
69 public String getType() {
70 return type;
71 }
73
75 public Node getStartNode() {
76 return start;
77 }
79
81 public Node getEndNode() {
82 return end;
83 }
85
87 public String toString() {
88 return "AnnotationImpl: id=" + id + "; type=" + type +
89 "; features=" + features + "; start=" + start +
90 "; end=" + end + System.getProperty("line.separator");
91 }
93
95 public int compareTo(Object o) throws ClassCastException {
96 Annotation other = (Annotation) o;
97 return id.compareTo(other.getId());
98 }
100
105
106 public int hashCode(){
107 int hashCodeRes = 0;
108 if (start != null && start.getOffset() != null)
109 hashCodeRes ^= start.getOffset().hashCode();
110 if (end != null && end.getOffset() != null)
111 hashCodeRes ^= end.getOffset().hashCode();
112 if(features != null)
113 hashCodeRes ^= features.hashCode();
114 return hashCodeRes;
115 }
117
121 public boolean equals(Object obj){
122 if(obj == null)
123 return false;
124 Annotation other;
125 if(obj instanceof AnnotationImpl){
126 other = (Annotation) obj;
127 }else return false;
128
129 if((type == null) ^ (other.getType() == null))
131 return false;
132 if(type != null && (!type.equals(other.getType())))
133 return false;
134
135 if((id == null) ^ (other.getId() == null))
137 return false;
138 if((id != null )&& (!id.equals(other.getId())))
139 return false;
140
141 if((start == null) ^ (other.getStartNode() == null))
143 return false;
144 if(start != null){
145 if((start.getOffset() == null) ^
146 (other.getStartNode().getOffset() == null))
147 return false;
148 if(start.getOffset() != null &&
149 (!start.getOffset().equals(other.getStartNode().getOffset())))
150 return false;
151 }
152
153 if((end == null) ^ (other.getEndNode() == null))
155 return false;
156 if(end != null){
157 if((end.getOffset() == null) ^
158 (other.getEndNode().getOffset() == null))
159 return false;
160 if(end.getOffset() != null &&
161 (!end.getOffset().equals(other.getEndNode().getOffset())))
162 return false;
163 }
164
165 if((features == null) ^ (other.getFeatures() == null))
167 return false;
168 if(features != null && (!features.equals(other.getFeatures())))
169 return false;
170 return true;
171 }
173
176 public void setFeatures(FeatureMap features) {
177 if (eventHandler != null)
179 this.features.removeFeatureMapListener(eventHandler);
180
181 this.features = features;
182
183 if (annotationListeners != null && ! annotationListeners.isEmpty())
186 this.features.addFeatureMapListener(eventHandler);
187
188 fireAnnotationUpdated(new AnnotationEvent(
190 this,
191 AnnotationEvent.FEATURES_UPDATED));
192
193
194 }
195
196
197
205 public boolean isCompatible(Annotation anAnnot){
206 if (anAnnot == null) return false;
207 if (coextensive(anAnnot)){
208 if (anAnnot.getFeatures() == null) return true;
209 if (anAnnot.getFeatures().subsumes(this.getFeatures()))
210 return true;
211 } return false;
213 }
215
228 public boolean isCompatible(Annotation anAnnot, Set aFeatureNamesSet){
229 if (aFeatureNamesSet == null) return isCompatible(anAnnot);
231 if (anAnnot == null) return false;
232 if (coextensive(anAnnot)){
233 if (anAnnot.getFeatures() == null) return true;
234 if (anAnnot.getFeatures().subsumes(this.getFeatures(),aFeatureNamesSet))
235 return true;
236 } return false;
238 }
240
247 public boolean isPartiallyCompatible(Annotation anAnnot){
248 if (anAnnot == null) return false;
249 if (overlaps(anAnnot)){
250 if (anAnnot.getFeatures() == null) return true;
251 if (anAnnot.getFeatures().subsumes(this.getFeatures()))
252 return true;
253 } return false;
255 }
257
271 public boolean isPartiallyCompatible(Annotation anAnnot,Set aFeatureNamesSet){
272 if (aFeatureNamesSet == null) return isPartiallyCompatible(anAnnot);
273 if (anAnnot == null) return false;
274 if (overlaps(anAnnot)){
275 if (anAnnot.getFeatures() == null) return true;
276 if (anAnnot.getFeatures().subsumes(this.getFeatures(),aFeatureNamesSet))
277 return true;
278 } return false;
280 }
282
289 public boolean coextensive(Annotation anAnnot){
290 if((anAnnot.getStartNode() == null) ^ (this.getStartNode() == null))
292 return false;
293
294 if(anAnnot.getStartNode() != null){
295 if((anAnnot.getStartNode().getOffset() == null) ^
296 (this.getStartNode().getOffset() == null))
297 return false;
298 if(anAnnot.getStartNode().getOffset() != null &&
299 (!anAnnot.getStartNode().getOffset().equals(
300 this.getStartNode().getOffset())))
301 return false;
302 }
304 if((anAnnot.getEndNode() == null) ^ (this.getEndNode() == null))
306 return false;
307
308 if(anAnnot.getEndNode() != null){
309 if((anAnnot.getEndNode().getOffset() == null) ^
310 (this.getEndNode().getOffset() == null))
311 return false;
312 if(anAnnot.getEndNode().getOffset() != null &&
313 (!anAnnot.getEndNode().getOffset().equals(
314 this.getEndNode().getOffset())))
315 return false;
316 }
318 return true;
320 }
322
327 public boolean overlaps(Annotation aAnnot){
328 if (aAnnot == null) return false;
329 if (aAnnot.getStartNode() == null ||
330 aAnnot.getEndNode() == null ||
331 aAnnot.getStartNode().getOffset() == null ||
332 aAnnot.getEndNode().getOffset() == null) return false;
333
334
342
343 if ( aAnnot.getEndNode().getOffset().longValue() <=
344 this.getStartNode().getOffset().longValue())
345 return false;
346
347 if ( aAnnot.getStartNode().getOffset().longValue() >=
348 this.getEndNode().getOffset().longValue())
349 return false;
350
351 return true;
352 }
354
358
366 private transient Vector annotationListeners;
367
370 protected EventsHandler eventHandler;
371
372
373
377 public synchronized void removeAnnotationListener(AnnotationListener l) {
378 if (annotationListeners != null && annotationListeners.contains(l)) {
379 Vector v = (Vector) annotationListeners.clone();
380 v.removeElement(l);
381 annotationListeners = v;
382 }
383 }
384
388 public synchronized void addAnnotationListener(AnnotationListener l) {
389 Vector v = annotationListeners == null ? new Vector(2) : (Vector) annotationListeners.clone();
390
391 if (v.isEmpty()) {
395 FeatureMap features = getFeatures();
396 if (eventHandler == null)
397 eventHandler = new EventsHandler();
398 features.addFeatureMapListener(eventHandler);
399 }
400
401 if (!v.contains(l)) {
402 v.addElement(l);
403 annotationListeners = v;
404 }
405 }
406
410 protected void fireAnnotationUpdated(AnnotationEvent e) {
411 if (annotationListeners != null) {
412 Vector listeners = annotationListeners;
413 int count = listeners.size();
414 for (int i = 0; i < count; i++) {
415 ((AnnotationListener) listeners.elementAt(i)).annotationUpdated(e);
416 }
417 }
418 }
420
421
425 Integer id;
426
430 String type;
431
435
436
439 Node start;
440
441
444 Node end;
445
446
447
448
449
453 class EventsHandler implements gate.event.FeatureMapListener, Serializable {
454 public void featureMapUpdated(){
455 fireAnnotationUpdated(new AnnotationEvent(
457 AnnotationImpl.this,
458 AnnotationEvent.FEATURES_UPDATED));
459 }
460 static final long serialVersionUID = 2608156420244752907L;
461
462 }
464
465 }