4A Server -  2.0
 All Classes Namespaces Files Functions Variables Enumerator
Annotation.java
Go to the documentation of this file.
1 /*
2  * Project: Server for annotations sharing
3  * Author: Ing. Jaroslav Dytrych idytrych@fit.vutbr.cz
4  * File: Annotation.java
5  * Description: Class representing annotation
6  */
7 
8 /**
9  * @file Annotation.java
10  *
11  * @brief Class representing annotation
12  */
13 
14 /**
15  * @package cz.vutbr.fit.knot.annotations.entity
16  *
17  * @brief Basic persistent entities
18  */
19 package cz.vutbr.fit.knot.annotations.entity;
20 
26 import cz.vutbr.fit.knot.annotations.entity.attribute.*;
31 import java.io.Serializable;
32 import java.text.SimpleDateFormat;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.Date;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40 import javax.persistence.Basic;
41 import javax.persistence.CascadeType;
42 import javax.persistence.Column;
43 import javax.persistence.Entity;
44 import javax.persistence.GeneratedValue;
45 import javax.persistence.GenerationType;
46 import javax.persistence.Id;
47 import javax.persistence.JoinColumn;
48 import javax.persistence.Lob;
49 import javax.persistence.NamedQueries;
50 import javax.persistence.NamedQuery;
51 import javax.persistence.OneToMany;
52 import javax.persistence.OneToOne;
53 import javax.persistence.Table;
54 import javax.persistence.Temporal;
55 import javax.persistence.TemporalType;
56 import javax.persistence.Transient;
57 import org.w3c.dom.Document;
58 
59 /**
60  * Class representing annotation
61  *
62  * @brief Class representing annotation
63  * @author idytrych
64  */
65 @Entity
66 @Table(name = "annotation")
67 @NamedQueries({
68  @NamedQuery(name = "Annotation.findAll", query = "SELECT a FROM Annotation a"),
69  @NamedQuery(name = "Annotation.findById", query = "SELECT a FROM Annotation a WHERE a.id = :id"),
70  @NamedQuery(name = "Annotation.findByType", query = "SELECT a FROM Annotation a WHERE a.type = :type"),
71  @NamedQuery(name = "Annotation.findByCreated", query = "SELECT a FROM Annotation a WHERE a.created = :created"),
72  @NamedQuery(name = "Annotation.findByAuthor", query = "SELECT a FROM Annotation a WHERE a.authorId = :authorId"),
73  @NamedQuery(name = "Annotation.findByAuthorName", query = "SELECT a FROM Annotation a WHERE a.authorName = :authorName"),
74  @NamedQuery(name = "Annotation.findByAuthorAddress", query = "SELECT a FROM Annotation a WHERE a.authorAddress = :authorAddress"),
75  @NamedQuery(name = "Annotation.findBySource", query = "SELECT a FROM Annotation a WHERE a.source = :source"),
76  @NamedQuery(name = "Annotation.findBySourceDocumentID", query = "SELECT a FROM Annotation a WHERE a.sourceDocumentId = :sourceDocumentId"),
77  @NamedQuery(name = "Annotation.findBySourceDocumentIDAndAuthor", query = "SELECT a FROM Annotation a WHERE a.sourceDocumentId = :sourceDocumentId AND a.authorId = :authorId"),
78  @NamedQuery(name = "Annotation.findBySourceDocumentIDNoNested", query = "SELECT a FROM Annotation a WHERE a.sourceDocumentId = :sourceDocumentId AND a.nestedIn IS NULL"),
79  @NamedQuery(name = "Annotation.findByNestedIn", query = "SELECT a FROM Annotation a WHERE a.nestedIn = :nestedIn")})
80 public class Annotation implements Serializable {
81  private static final long serialVersionUID = 1L;
82  /** Id of annotation */
83  @Id
84  @GeneratedValue(strategy = GenerationType.IDENTITY)
85  @Basic(optional = false)
86  @Column(name = "id")
87  private Integer id;
88  /** Id of type of annotation */
89  @Basic(optional = false)
90  @Column(name = "type", nullable=false, insertable=false, updatable=false)
91  private Integer type;
92  /** Date of creation */
93  @Basic(optional = false)
94  @Column(name = "created")
95  @Temporal(TemporalType.TIMESTAMP)
96  private Date created;
97  /** URI of annotation author (user) */
98  @Basic(optional = false)
99  @Column(name = "authorIdStr")
100  private String authorIdStr;
101  /** Name of annotation author (user) */
102  @Basic(optional = true)
103  @Column(name = "authorName")
104  private String authorName;
105  /** E-mail of annotation author (user) */
106  @Basic(optional = true)
107  @Column(name = "authorAddress")
108  private String authorAddress;
109  /** Id of annotation author (user) */
110  @Basic(optional = true)
111  @Column(name = "authorId", insertable=false, updatable=false)
112  private String authorId;
113  /** URI of annotated copy of document to which this annotation belongs */
114  @Basic(optional = false)
115  @Column(name = "source")
116  private String source;
117  /** Id of annotated copy of document to which this annotation belongs */
118  @Basic(optional = false)
119  @Column(name = "sourceDocumentId", nullable=false, insertable=false, updatable=false)
120  private Integer sourceDocumentId;
121  /** Textual content of annotation */
122  @Basic(optional = false)
123  @Lob
124  @Column(name = "content")
125  private String content;
126  /** If this annotation is nested, here is id of parent annotation */
127  @Column(name = "nestedIn", insertable=false, updatable=false)
128  private String nestedIn;
129 
130  /** Type of annotation */
131  @OneToOne(optional = false)
132  @JoinColumn(name = "type", referencedColumnName = "id")
133  private AnnotType annotType;
134  /** Annotated copy of document to which this annotation belongs */
135  @OneToOne(optional = false)
136  @JoinColumn(name = "sourceDocumentId", referencedColumnName = "id")
137  private AnnotDocument sourceDocument;
138  /** List of attributes of annotation */
139  @OneToMany(mappedBy = "refAnnotation", cascade = CascadeType.ALL,
140  targetEntity = BaseAttribute.class)
141  private List<BaseAttribute> attributes;
142  /** List of annotated fragments */
143  @OneToMany(mappedBy = "refAnnotation", cascade = CascadeType.ALL,
144  targetEntity = Fragment.class)
145  private List<Fragment> fragments;
146  /** Author of annotation (user) */
147  @OneToOne(optional = true)
148  @JoinColumn(name = "authorId", referencedColumnName = "id")
149  private User user;
150  /** If this annotation is nested, here is parent annotation */
151  @OneToOne(optional = true)
152  @JoinColumn(name = "nestedIn", referencedColumnName = "id")
153  private Annotation nestedInAnnot;
154 
155  /** Temporary id for links between annotations which are not saved yet */
156  @Transient
157  private String tmpId;
158  /** Holds IDs of annotations that have a linkedAnnotation attribute with
159  * value pointing to this annotation. It is necessary to store these IDs
160  * before the annotation is removed from the database (before persist).
161  * The list is used during flier processing when user has annotations
162  * that he is not subscribed to and they need to be removed from the client.
163  */
164  @Transient
165  private List<Integer> linkedByBeforeRemove;
166 
167  /**
168  * Constructor
169  */
170  public Annotation() {
171  }
172 
173  /**
174  * Constructor of reference objects for searching purposes - no initialization
175  * needed
176  *
177  * @param id Id of annotation
178  */
179  public Annotation(Integer id) {
180  this.id = id;
181  }
182 
183  /**
184  * Constructor
185  *
186  * @param id Id of annotation
187  * @param created Date of creation
188  * @param authorIdStr URI of annotation author (user)
189  * @param authorName Name of annotation author (user)
190  * @param authorAddress E-mail of annotation author (user)
191  * @param sourceDocument Annotated copy of document to which this annotation belongs
192  * @param content Textual content of annotation
193  * @param nestedIn If this annotation is nested, then parent annotation, null otherwise
194  */
195  public Annotation(Integer id, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content, String nestedIn) {
196  this.id = id;
197  this.created = created;
198  this.authorIdStr = authorIdStr;
199  this.authorName = authorName;
200  this.authorAddress = authorAddress;
201  this.sourceDocument = sourceDocument;
202  if (sourceDocument != null) {
203  this.source = sourceDocument.getUriForAnnot();
204  }
205  this.content = content;
206  this.nestedIn = nestedIn;
207  this.nestedInAnnot = null;
208  this.attributes = new ArrayList<BaseAttribute>();
209  this.fragments = new ArrayList<Fragment>();
210  }
211 
212  /**
213  * Constructor
214  *
215  * @param annotType Type of annotation
216  * @param created Date of creation
217  * @param authorIdStr URI of annotation author (user)
218  * @param authorName Name of annotation author (user)
219  * @param authorAddress E-mail of annotation author (user)
220  * @param sourceDocument Annotated copy of document to which this annotation belongs
221  * @param content Textual content of annotation
222  */
223  public Annotation(AnnotType annotType, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content) {
224  this.annotType = annotType;
225  this.created = created;
226  this.authorIdStr = authorIdStr;
227  this.authorName = authorName;
228  this.authorAddress = authorAddress;
229  this.sourceDocument = sourceDocument;
230  if (sourceDocument != null) {
231  this.source = sourceDocument.getUriForAnnot();
232  }
233  this.content = content;
234  this.nestedInAnnot = null;
235  this.attributes = new ArrayList<BaseAttribute>();
236  this.fragments = new ArrayList<Fragment>();
237  }
238 
239  /**
240  * Constructor
241  *
242  * @param annotType Type of annotation
243  * @param created Date of creation
244  * @param authorIdStr URI of annotation author (user)
245  * @param authorName Name of annotation author (user)
246  * @param authorAddress E-mail of annotation author (user)
247  * @param sourceDocument Annotated copy of document to which this annotation belongs
248  * @param content Textual content of annotation
249  * @param nestedInAnnot If this annotation is nested, then parent annotation, null otherwise
250  */
251  public Annotation(AnnotType annotType, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content, Annotation nestedInAnnot) {
252  this.annotType = annotType;
253  this.created = created;
254  this.authorIdStr = authorIdStr;
255  this.authorName = authorName;
256  this.authorAddress = authorAddress;
257  this.sourceDocument = sourceDocument;
258  if (sourceDocument != null) {
259  this.source = sourceDocument.getUriForAnnot();
260  }
261  this.content = content;
262  this.nestedInAnnot = nestedInAnnot;
263  this.attributes = new ArrayList<BaseAttribute>();
264  this.fragments = new ArrayList<Fragment>();
265  }
266 
267  /**
268  * Updates data in this annotation with data from another annotation
269  *
270  * @param newData Annotation with new data
271  */
272  public void updateWithAnnotation(Annotation newData) {
273  this.type = newData.getAnnotType().getId();
274  this.created = newData.getCreated();
275  this.authorIdStr = newData.getAuthorIdStr();
276  this.authorName = newData.getAuthorName();
277  this.authorAddress = newData.getAuthorAddress();
278  this.source = newData.getSource();
279  this.sourceDocumentId = newData.getSourceDocument().getId();
280  this.content = newData.getContent();
281  if (newData.getNestedInAnnot() != null) {
282  this.nestedIn = newData.getNestedInAnnot().getId().toString();
283  }
284  this.annotType = newData.getAnnotType();
285  this.sourceDocument = newData.getSourceDocument();
286  this.attributes = newData.getAttributes();
287  this.fragments = newData.getFragments();
288  this.user = newData.getUser();
289  this.nestedInAnnot = newData.getNestedInAnnot();
290  }
291 
292  /**
293  * Updates data in this annotation with data from some suggestion
294  *
295  * @param newData Suggestion with new data
296  */
297  public void updateWithSuggestion(Suggestion newData) {
298  this.type = newData.getAnnotType().getId();
299  this.created = newData.getCreated();
300  this.authorIdStr = newData.getAuthorIdStr();
301  this.authorName = newData.getAuthorName();
302  this.authorAddress = newData.getAuthorAddress();
303  this.source = newData.getSource();
304  this.sourceDocumentId = newData.getSourceDocument().getId();
305  this.content = newData.getContent();
306  // We do not need to set this.nestedInAnnot - it will be set later
307  this.annotType = newData.getAnnotType();
308  this.sourceDocument = newData.getSourceDocument();
309  this.fragments = new ArrayList<Fragment>();
310  if (newData.getFragments() != null) {
311  Iterator<SuggestionFragment> frIt = newData.getFragments().iterator();
312  while (frIt.hasNext()) {
313  SuggestionFragment sugFr = frIt.next();
314  Fragment newFr = new Fragment(sugFr.getPath(), sugFr.getOffset(), sugFr.getLength(), sugFr.getAnnotatedText(), this);
315  fragments.add(newFr);
316  }
317  }
318  this.attributes = new ArrayList<BaseAttribute>();
319  if (newData.getAttributes() != null) {
320  Iterator<SugBaseAttribute> atIt = newData.getAttributes().iterator();
321  while (atIt.hasNext()) {
322  SugBaseAttribute sugAt = atIt.next();
323  BaseAttribute newAt = null;
324  String simpleType = sugAt.getSimpleType();
325  if (simpleType != null && simpleType.equals("SuggestionLink")) {
326  simpleType = "AnnotationLink";
327  } else if (simpleType != null && simpleType.equals("NestedSuggestion")) {
328  simpleType = "NestedAnnotation";
329  }
330  try {
331  newAt = AttributeManager.createAttribute(sugAt.getName(), simpleType, this);
332  } catch (ClassNotFoundException ex) {
333  String msg = "Unable to create annotation attribute with type = " + sugAt.getSimpleType();
334  Logger.getLogger(Annotation.class.getName()).log(Level.SEVERE, null, msg);
335  continue;
336  }
337  newAt.updateFromSugBaseAttributeAll(sugAt);
338  this.attributes.add(newAt);
339  }
340  }
341  this.user = newData.getUser();
342  }
343 
344  /**
345  * Gets id of annotation
346  *
347  * @return Returns id of annotation
348  */
349  public Integer getId() {
350  return id;
351  }
352 
353  /**
354  * Sets id of annotation
355  *
356  * @param id Id of annotation
357  */
358  public void setId(Integer id) {
359  this.id = id;
360  }
361 
362  /**
363  * Gets type of annotation
364  *
365  * @return Returns type of annotation
366  */
368  return annotType;
369  }
370 
371  /**
372  * Sets type of annotation
373  *
374  * @param annotType Type of annotation
375  */
376  public void setAnnotType(AnnotType annotType) {
377  this.annotType = annotType;
378  }
379 
380  /**
381  * Gets author of annotation (user)
382  *
383  * @return Returns author of annotation (user)
384  */
385  public User getUser() {
386  return user;
387  }
388 
389  /**
390  * Sets author of annotation (user)
391  * URI is also set and if available, full name and e-mail too
392  *
393  * @param user Author of annotation (user)
394  */
395  public void setUser(User user) {
396  this.user = user;
397  if (user != null) {
398  authorIdStr = user.getURI();
399  if (user.getName() != null && !user.getName().contentEquals("")) {
400  authorName = user.getName();
401  }
402  if (user.getEmail() != null && !user.getEmail().contentEquals("")) {
403  authorAddress = user.getEmail();
404  }
405  }
406  }
407 
408  /**
409  * Gets date of creation
410  *
411  * @return Returns date of creation
412  */
413  public Date getCreated() {
414  return created;
415  }
416 
417  /**
418  * Sets date of creation
419  *
420  * @param created Date of creation
421  */
422  public void setCreated(Date created) {
423  this.created = created;
424  }
425 
426  /**
427  * Gets URI of author of annotation (user)
428  *
429  * @return Returns URI of author of annotation (user)
430  */
431  public String getAuthorIdStr() {
432  return authorIdStr;
433  }
434 
435  /**
436  * Sets URI of author of annotation (user)
437  *
438  * @param authorIdStr URI of author of annotation (user)
439  */
440  public void setAuthorIdStr(String authorIdStr) {
441  this.authorIdStr = authorIdStr;
442  }
443 
444  /**
445  * Gets name of author of annotation (user)
446  *
447  * @return Returns name of author of annotation (user)
448  */
449  public String getAuthorName() {
450  return authorName;
451  }
452 
453  /**
454  * Sets name of author of annotation (user)
455  *
456  * @param authorName Name of author of annotation (user)
457  */
458  public void setAuthorName(String authorName) {
459  this.authorName = authorName;
460  }
461 
462  /**
463  * Gets e-mail of author of annotation (user)
464  *
465  * @return Returns e-mail of author of annotation (user)
466  */
467  public String getAuthorAddress() {
468  return authorAddress;
469  }
470 
471  /**
472  * Sets e-mail of author of annotation (user)
473  *
474  * @param authorAddress E-mail of author of annotation (user)
475  */
476  public void setAuthorAddress(String authorAddress) {
477  this.authorAddress = authorAddress;
478  }
479 
480  /**
481  * Gets annotated copy of document to which this annotation belongs
482  *
483  * @return Returns annotated copy of document to which this annotation belongs
484  */
485  public String getSource() {
486  return source;
487  }
488 
489  /**
490  * Sets annotated copy of document to which this annotation belongs
491  *
492  * @param source Annotated copy of document to which this annotation belongs
493  */
494  public void setSource(String source) {
495  this.source = source;
496  }
497 
498  /**
499  * Gets list of annotated fragments
500  *
501  * @return Returns list of annotated fragments
502  */
503  public List<Fragment> getFragments() {
504  return fragments;
505  }
506 
507  /**
508  * Gets list of annotated fragments as ArrayList
509  *
510  * @return Returns list of annotated fragments as ArrayList
511  */
512  public ArrayList<Fragment> getFragmentsAL() {
513  return new ArrayList<Fragment>(fragments);
514  }
515 
516  /**
517  * Sets list of annotated fragments
518  *
519  * @param fragments List of annotated fragments
520  */
521  public void setFragments(ArrayList<Fragment> fragments) {
522  this.fragments = fragments;
523  }
524 
525  /**
526  * Adds fragment to the list of annotated fragments
527  *
528  * @param fragment Annotated fragment
529  */
530  public void addFragment(Fragment fragment) {
531  fragments.add(fragment);
532  }
533 
534  /**
535  * Gets textual content of annotation
536  *
537  * @return Returns textual content of annotation
538  */
539  public String getContent() {
540  return content;
541  }
542 
543  /**
544  * Sets textual content of annotation
545  *
546  * @param content Textual content of annotation
547  */
548  public void setContent(String content) {
549  this.content = content;
550  }
551 
552  /**
553  * Gets id of parent annotation of nested annotation
554  *
555  * @return If this annotation is nested, returns id of parent annotation, null otherwise
556  */
557  public String getNestedIn() {
558  return nestedIn;
559  }
560 
561  /**
562  * Sets id of parent annotation of nested annotation
563  *
564  * @param nestedIn Id of parent annotation of nested annotation
565  */
566  public void setNestedIn(String nestedIn) {
567  this.nestedIn = nestedIn;
568  }
569 
570  /**
571  * Gets list of annotation attributes
572  *
573  * @return Returns list of annotation attributes
574  */
575  public List<BaseAttribute> getAttributes() {
576  return attributes;
577  }
578 
579  /**
580  * Sets list of annotation attributes
581  *
582  * @param attributes List of annotation attributes
583  */
584  public void setAttributes(ArrayList<BaseAttribute> attributes) {
585  this.attributes = attributes;
586  }
587 
588  /**
589  * Adds attribute to the annotation
590  *
591  * @param attribute Annotation attribute to add
592  */
593  public void addAttribute(BaseAttribute attribute) {
594  this.attributes.add(attribute);
595  }
596 
597  /**
598  * Gets parent annotation of nested annotation
599  *
600  * @return If this annotation is nested, returns parent annotation, null otherwise
601  */
603  return nestedInAnnot;
604  }
605 
606  /**
607  * Sets parent annotation of nested annotation
608  *
609  * @param nestedInAnnot If this annotation is nested, then parent annotation, null otherwise
610  */
611  public void setNestedInAnnot(Annotation nestedInAnnot) {
612  this.nestedInAnnot = nestedInAnnot;
613  }
614 
615  /**
616  * Gets id of annotated copy of document to which this annotation belongs
617  *
618  * @return Returns id of annotated copy of document to which this annotation belongs
619  */
620  public Integer getSourceDocumentId() {
621  return sourceDocumentId;
622  }
623 
624  /**
625  * Sets id of annotated copy of document to which this annotation belongs
626  *
627  * @param sourceDocumentId id of annotated copy of document to which this annotation belongs
628  */
629  public void setSourceDocumentId(Integer sourceDocumentId) {
630  this.sourceDocumentId = sourceDocumentId;
631  }
632 
633  /**
634  * Gets id of type of annotation
635  *
636  * @return Returns id of type of annotation
637  */
638  public Integer getType() {
639  return type;
640  }
641 
642  /**
643  * Sets id of type of annotation
644  *
645  * @param type id of type of annotation
646  */
647  public void setType(Integer type) {
648  this.type = type;
649  }
650 
651  /**
652  * Gets annotated copy of document to which this annotation belongs
653  *
654  * @return Returns annotated copy of document to which this annotation belongs
655  */
657  return sourceDocument;
658  }
659 
660  /**
661  * Sets annotated copy of document to which this annotation belongs
662  * (if document is not null, his URI is also set)
663  *
664  * @param sourceDocument Annotated copy of document to which this annotation belongs
665  */
666  public void setSourceDocument(AnnotDocument sourceDocument) {
667  this.sourceDocument = sourceDocument;
668  if (sourceDocument != null) {
669  this.source = sourceDocument.getUriForAnnot();
670  }
671  }
672 
673  /**
674  * Gets id of annotation author (user)
675  *
676  * @return Returns id of annotation author (user)
677  */
678  public String getAuthorId() {
679  return authorId;
680  }
681 
682  /**
683  * Sets id of annotation author (user)
684  *
685  * @param authorId id of annotation author (user)
686  */
687  public void setAuthorId(String authorId) {
688  this.authorId = authorId;
689  }
690 
691  /**
692  * Gets URI of annotation
693  *
694  * @return URI of annotation
695  */
696  public String getURI() {
697  if (id == null) {
698  return "";
699  }
700  return AppBean.getBaseAnnotUri() + id;
701  }
702 
703  /**
704  * Gets URI of annotation for protocol V2
705  *
706  * @return URI of annotation
707  */
708  public String getURIV2() {
709  if (id != null) {
710  return AppBean.getBaseUri() + "/serv/" + id;
711  }
712  else if(tmpId != null){
713  return AppBean.getBaseUri() + "/temp/" + tmpId;
714  }
715  else{
716  return "";
717  }
718  }
719 
720  @Override
721  public int hashCode() {
722  int hash = 0;
723  hash += (id != null ? id.hashCode() : 0);
724  return hash;
725  }
726 
727  /**
728  * Compares this with other object and returns, whether objects are same type
729  * and have same id.
730  *
731  * @param object Object to compare with
732  * @return If object is same type and have same id, returns true, false otherwise
733  */
734  @Override
735  public boolean equals(Object object) {
736  if (!(object instanceof Annotation)) {
737  return false;
738  }
739  Annotation other = (Annotation) object;
740  if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
741  return false;
742  }
743 
744  if(other.id == null && this.id == null){
745  if(!contentEquals(object)){
746  return false;
747  }
748  }
749 
750  return true;
751  }
752 
753  /**
754  * Compares this with other object and returns, whether objects are same type
755  * and have same id, but not go to deeper comparation if noLinek is set to true.
756  *
757  * @param object Object to compare with
758  * @param noLinked No trace links and compare them if is set to true
759  * @return If object is same type and have same id, returns true, false otherwise
760  */
761  public boolean equals(Object object, boolean noLinked){
762  if (!(object instanceof Annotation)) {
763  return false;
764  }
765  Annotation other = (Annotation) object;
766  if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
767  return false;
768  }
769 
770  if(other.id == null && this.id == null){
771  if(!contentEquals(object,false,noLinked)){
772  return false;
773  }
774  }
775 
776  return true;
777  }
778 
779  /**
780  * Compares this with other object and returns, whether objects are same type
781  * and have same content (id is irelevant). Contents of fragments
782  * and attributes are also compared.
783  *
784  * @param obj Object to compare with
785  * @return If object is same type and have same content, returns true, false otherwise
786  */
787  public boolean contentEquals(Object obj) {
788  return contentEquals(obj,false,false);
789  }
790 
791  /**
792  * Compares this with other object and returns, whether objects are same type
793  * and have same content (id is irrelevant). Contents of fragments
794  * and attributes are also compared.
795  *
796  * @param obj Object to compare with
797  * @param withCreated If true, dates of creation will be compared, if false, dates will be omitted
798  * @param noLinked If true, linked attributes will be ignored, if false, links will be compared.
799  * @return If object is same type and have same content, returns true, false otherwise
800  */
801  public boolean contentEquals(Object obj, boolean withCreated, boolean noLinked) {
802  if (obj == null) {
803  return false;
804  }
805  if (getClass() != obj.getClass()) {
806  return false;
807  }
808  final Annotation other = (Annotation) obj;
809  if (withCreated) {
810  if (this.created != other.created && (this.created == null || !this.created.equals(other.created))) {
811  return false;
812  }
813  }
814  if ((this.authorIdStr == null) ? (other.authorIdStr != null) : !this.authorIdStr.equals(other.authorIdStr)) {
815  return false;
816  }
817  if ((this.authorName == null) ? (other.authorName != null) : !this.authorName.equals(other.authorName)) {
818  return false;
819  }
820  if ((this.authorAddress == null) ? (other.authorAddress != null) : !this.authorAddress.equals(other.authorAddress)) {
821  return false;
822  }
823  if ((this.source == null) ? (other.source != null) : !this.source.equals(other.source)) {
824  return false;
825  }
826  if ((this.content == null) ? (other.content != null) : !this.content.equals(other.content)) {
827  return false;
828  }
829  if (this.annotType != other.annotType && (this.annotType == null || !this.annotType.equals(other.annotType))) {
830  return false;
831  }
832  if (this.sourceDocument != other.sourceDocument && (this.sourceDocument == null || !this.sourceDocument.equals(other.sourceDocument))) {
833  return false;
834  }
835  if (this.tmpId != other.tmpId && (this.tmpId == null || !this.tmpId.equals(other.tmpId))) {
836  return false;
837  }
838 
839  if (this.attributes == null && other.attributes != null) {
840  return false;
841  } else if (this.attributes != null && other.attributes == null) {
842  return false;
843  } else if (this.attributes != other.attributes && this.attributes != null && other.attributes != null) {
844  if (this.attributes.size() != other.attributes.size()) {
845  return false;
846  }
847  Iterator<BaseAttribute> atIt = this.attributes.iterator();
848  while (atIt.hasNext()) {
849  BaseAttribute at = atIt.next();
850  boolean found = false;
851  Iterator<BaseAttribute> oAtIt = other.attributes.iterator();
852  if(noLinked && at instanceof LinkedAnnotationAttribute){
853  continue;
854  }
855  while (oAtIt.hasNext()) {
856  BaseAttribute oAt = oAtIt.next();
857 
858  if(at instanceof LinkedAnnotationAttribute && oAt instanceof LinkedAnnotationAttribute){
859  if(at.getValue() != null && ((Annotation)at.getValue()).equals(oAt,true)){
860  found = true;
861  break;
862  }
863  }
864 
865  if (at.contentEquals(oAt,false)) {
866  found = true;
867  break;
868  }
869  }
870  if (!found) {
871  return false;
872  }
873  }
874  }
875  if (this.fragments == null && other.fragments != null) {
876  return false;
877  } else if (this.fragments != null && other.fragments == null) {
878  return false;
879  } else if (this.fragments != other.fragments && this.fragments != null && other.fragments != null) {
880  if (this.fragments.size() != other.fragments.size()) {
881  return false;
882  }
883  Iterator<Fragment> frIt = this.fragments.iterator();
884  while (frIt.hasNext()) {
885  Fragment fr = frIt.next();
886  boolean found = false;
887  Iterator<Fragment> oFrIt = other.fragments.iterator();
888  while (oFrIt.hasNext()) {
889  Fragment oFr = oFrIt.next();
890  if (fr.contentEquals(oFr)) {
891  found = true;
892  break;
893  }
894  }
895  if (!found) {
896  return false;
897  }
898  }
899  }
900  if (this.user != other.user && (this.user == null || !this.user.equals(other.user))) {
901  return false;
902  }
903  if (this.nestedInAnnot == null && other.nestedInAnnot != null) {
904  return false;
905  } else if (this.nestedInAnnot != null && other.nestedInAnnot == null) {
906  return false;
907  }
908  return true;
909  } // contentEquals()
910 
911  @Override
912  public String toString() {
913  return "cz.vutbr.fit.knot.annotations.entity.Annotation[id=" + id + ",content=" + content + "]";
914  }
915 
916  /**
917  * Returns serialized informations about annotation in SXML
918  *
919  * @param addSpaces If true, it will add space after each node during linearization
920  * (offset will be incremented by 1)
921  * @return Returns serialized informations about annotation in SXML
922  */
923  public String toSXMLString(boolean addSpaces) {
924  return toSXMLString(addSpaces, false);
925  }
926 
927  /**
928  * Returns serialized informations about annotation in SXML
929  *
930  * @param addSpaces If true, it will add space after each node during linearization
931  * (offset will be incremented by 1)
932  * @param addCreated If true, date and time of creation will be added
933  * @return Returns serialized informations about annotation in SXML
934  */
935  public String toSXMLString(boolean addSpaces, boolean addCreated){
936  StringBuilder sb = new StringBuilder();
937 
938  ArrayList<Fragment> linearized = new ArrayList<Fragment>();
939 
940  if (fragments != null && !fragments.isEmpty()) { // if there are some fragments
941 
942  //Linearize fragments
943  ArrayList<ArrayList<Fragment>> tmpList = new ArrayList<ArrayList<Fragment>>();
944  ArrayList<ArrayList<Fragment>> failed = new ArrayList<ArrayList<Fragment>>();
945  tmpList.add(new ArrayList<Fragment>(fragments));
946  MatcherProvider mProvider = new MatcherProvider();
947  Document doc = null;
948 
949  try {
950  doc = mProvider.getDocumentFromString(sourceDocument.getContent(), true, true);
951  } catch (Exception ex) {
952  String msg = "Error while parsing the annotated document.";
953  Logger.getLogger(Annotation.class.getName()).log(Level.SEVERE, msg, ex);
954  }
955 
956  linearized = Linearizer.fragmentsToLinFragments(tmpList, doc, failed, addSpaces);
957 
958  if (!failed.isEmpty()) {
959  ArrayList<Fragment> failedList = failed.get(0);
960  if (!failedList.isEmpty()) {
961  String msg = "Error during linearization of fragments.";
962  Logger.getLogger(Annotation.class.getName()).log(Level.SEVERE, msg);
963  }
964  }
965  } // if there are some fragments
966 
967  if (!linearized.isEmpty()) {
968  Fragment fragment = linearized.get(0);
969  if (fragment != null) {
970  sb.append("<text s_offset=\"").append(fragment.getOffset()).append("\" ");
971  sb.append("e_offset=\"").append((fragment.getOffset() + fragment.getLength())).append("\" ");
972  sb.append("string=\"").append(Util.escapeForXml(fragment.getAnnotatedText())).append("\">");
973  } else {
974  String msg = "Error during linearization of fragments.";
975  Logger.getLogger(Annotation.class.getName()).log(Level.SEVERE, msg);
976  linearized = new ArrayList<Fragment>();
977  }
978  }
979 
980  String createdStr = "";
981  if (addCreated) {
982  createdStr = " created=\"" + Util.toRFC3339Date(created) + "\"";
983  }
984 
985  sb.append("<annotation type=\"").append(annotType.getName()).append("\" id=\"").append(getURI()).append("\"").append(createdStr).append(">");
986 
987  //Serialize all annotation attributes
988 
989  if (attributes != null) {
990  Iterator<BaseAttribute> attIt = attributes.iterator();
991 
992  while (attIt.hasNext()) {
993  BaseAttribute tmpAtt = attIt.next();
994  sb.append(tmpAtt.toSXMLString());
995  }
996 
997  }
998 
999  sb.append("</annotation>");
1000 
1001  if (!linearized.isEmpty()) {
1002  sb.append("</text>");
1003  }
1004 
1005  return sb.toString();
1006  }
1007 
1008  /**
1009  * Returns serialized informations about annotation in XML for protocol V2
1010  *
1011  * @param attFilter Filter for attributes
1012  * @param langNum Number of language
1013  * @param KBRefMode Is KB_Ref mode on?
1014  * @return Returns serialized informations about annotation in XML for protocol V2
1015  */
1016  public String toXMLStringV2(ArrayList<String> attFilter, int langNum, Boolean KBRefMode){
1017  if (attFilter == null) {
1018  attFilter = new ArrayList<String>();
1019  attFilter.add(Constants.UPDATABLE_AN_AT_NAME);
1020  }
1021  if (KBRefMode == null) {
1022  KBRefMode = false;
1023  }
1024  StringBuilder result = new StringBuilder();
1025  String annotUri = getURIV2();
1026 
1027  // serialize annotation + annotation uri
1028  result.append("<oa:Annotation rdf:about=\"");
1029  result.append(annotUri);
1030  result.append("\">");
1031 
1032  // serialize annotation type
1033  result.append("<oa:hasBody>");
1034  result.append("<oa:SemanticTag rdf:about=\"");
1035  result.append(annotType.getUri());
1036  result.append("\"/>");
1037  result.append("</oa:hasBody>");
1038 
1039  // serialize fragments
1040  if(fragments == null || fragments.isEmpty()){
1041  // annotation of whole document
1042  result.append("<oa:hasTarget>");
1043 
1044  result.append("<dctypes:Text rdf:about=\"");
1045  result.append(source);
1046  result.append("\">");
1047  result.append("<dc:format>text/xml</dc:format>");
1048  result.append("</dctypes:Text>");
1049 
1050  result.append("</oa:hasTarget>");
1051  } else if (fragments.size() == 1) {
1052  // annotation have only one fragment
1053  result.append("<oa:hasTarget>");
1054  result.append(((Fragment) fragments.get(0)).toXMLStringV2());
1055  result.append("</oa:hasTarget>");
1056  } else if (fragments.size() > 1) {
1057  // annotation with multiple fragments
1058  result.append("<oa:hasTarget>");
1059  result.append("<oa:Composite rdf:about=\"");
1060  // make uri of composite
1061  result.append(source);
1062  result.append(getFragmentXpointersV2());
1063  result.append("\">");
1064 
1065  Iterator<Fragment> fragIt = fragments.iterator();
1066  while(fragIt.hasNext()){
1067  Fragment tmpFrag = fragIt.next();
1068  result.append("<oa:item>");
1069  result.append(tmpFrag.toXMLStringV2());
1070  result.append("</oa:item>");
1071  }
1072 
1073  result.append("</oa:Composite>");
1074  result.append("</oa:hasTarget>");
1075  }
1076 
1077  // serialize annotation content
1078  result.append("<oa:hasBody>");
1079 
1080  result.append("<cnt:ContentAsText rdf:about=\"");
1081  result.append(annotUri);
1082  result.append("#body\">");
1083 
1084  result.append("<rdf:type rdf:resource=\"http://purl.org/dc/dcmitype/Text\"/>");
1085  result.append("<cnt:chars><![CDATA[");
1086  result.append(content);
1087  result.append("]]></cnt:chars><dc:format>text/plain</dc:format>");
1088  result.append("</cnt:ContentAsText>");
1089  result.append("</oa:hasBody>");
1090 
1091 
1092  // serialize attributes
1093  result.append("<oa:hasBody>");
1094 
1095  result.append("<cnt:ContentAsText rdf:about=\"");
1096  result.append(source);
1097  result.append("\">");
1098 
1099  result.append("<rdf:type rdf:resource=\"http://www.w3.org/2004/03/trix/rdfg-1/Graph\"/>");
1100 
1101  result.append("<trix:TriX>");
1102  result.append("<trix:graph>");
1103 
1104  if (KBRefMode
1105  && !Constants.FORBIDDEN_ENTITY_TYPES.contains(this.getAnnotType().getName().toLowerCase())
1106  && canBeDisplayedInKBRefMode()) {
1107  // KB_Ref mode
1108  result.append(attributesToKBRefString(attFilter, langNum));
1109  } else {
1110  Collections.sort(attributes);
1111  Iterator<BaseAttribute> attribIt = attributes.iterator();
1112  while (attribIt.hasNext()) {
1113  BaseAttribute tmpAttrib = attribIt.next();
1114  if (!AttributeManager.hasAttributeRightInstance(tmpAttrib)) {
1115  tmpAttrib = AttributeManager.changeAttributeInstance(tmpAttrib);
1116  }
1117  String aName = tmpAttrib.getName();
1118  if (attFilter.contains(aName)) {
1119  continue;
1120  }
1121  result.append(tmpAttrib.toXMLStringV2());
1122  }
1123  }
1124 
1125  result.append("</trix:graph>");
1126  result.append("</trix:TriX>");
1127 
1128  result.append("<dc:format>text/xml</dc:format>");
1129  result.append("</cnt:ContentAsText>");
1130  result.append("</oa:hasBody>");
1131 
1132  // serialize informations about date of creation
1133  result.append("<oa:annotatedBy>");
1134 
1135  result.append("<foaf:Person rdf:about=\"");
1136  result.append(user.getURIV2());
1137  result.append("\">");
1138 
1139  result.append("<foaf:mbox>mailto:");
1140  result.append(authorAddress);
1141  result.append("</foaf:mbox>");
1142 
1143  result.append("<foaf:name>");
1144  result.append(authorName);
1145  result.append("</foaf:name>");
1146 
1147  result.append("</foaf:Person>");
1148  result.append("</oa:annotatedBy>");
1149 
1150 
1151  // serialize time and date of creation
1152  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
1153  String date = df.format(created);
1154 
1155  result.append("<oa:annotatedAt>");
1156  result.append(date);
1157  result.append("</oa:annotatedAt>");
1158 
1159  result.append("<oa:serializedAt>");
1160  result.append(date);
1161  result.append("</oa:serializedAt>");
1162 
1163  // end of annotation
1164  result.append("</oa:Annotation>");
1165 
1166  //Serializing all nested annotations
1167  Iterator<BaseAttribute> attrNestedIt = attributes.iterator();
1168  while (attrNestedIt.hasNext()) {
1169  BaseAttribute tmpAttrib = attrNestedIt.next();
1170  String aName = tmpAttrib.getName();
1171  if (attFilter.contains(aName)) {
1172  continue;
1173  }
1174  if (tmpAttrib.getNestedAnnotation() != null) {
1175  result.append(tmpAttrib.getNestedAnnotation().toXMLStringV2(attFilter, langNum, KBRefMode));
1176  }
1177  }
1178 
1179  return result.toString();
1180  }
1181 
1182  /**
1183  * If this annotation can be displayed in KB Ref mode (KB_Ref attribute
1184  * is not presented and updatable_annotation is presented and true),
1185  * returns true, false otherwise
1186  *
1187  * @return If this annotation can be displayed in KB Ref mode, returns true, false otherwise
1188  */
1189  private boolean canBeDisplayedInKBRefMode() {
1190  Iterator<BaseAttribute> attrIt = attributes.iterator();
1191  boolean isUpdatableAnnot = false;
1192  while(attrIt.hasNext()){
1193  BaseAttribute tmpAttrib = attrIt.next();
1194  if (tmpAttrib.getName().contentEquals(Constants.KB_REF_ATT_NAME)) {
1195  return false;
1196  }
1197  if (tmpAttrib.getName().contentEquals(Constants.UPDATABLE_AN_AT_NAME)) {
1198  isUpdatableAnnot = tmpAttrib.getBoolValue();
1199  }
1200  }
1201  return isUpdatableAnnot;
1202  }
1203 
1204  /**
1205  * Returns serialized attributes in KB Ref mode
1206  *
1207  * @param attFilter Filter for attributes
1208  * @param langNum Number of language
1209  * @return Returns serialized attributes in KB Ref mode
1210  */
1211  private StringBuilder attributesToKBRefString(ArrayList<String> attFilter, int langNum) {
1212  StringBuilder result = new StringBuilder();
1213  StringBuilder tmpResult = new StringBuilder();
1214  Iterator<BaseAttribute> attribIt = attributes.iterator();
1215  EntityAttribute kRefAt = new EntityAttribute();
1216  kRefAt.setSimpleType("Entity");
1217  kRefAt.setEntityAdditionalAttributes(new ArrayList<EntityAdditionalAttribute>());
1218  kRefAt.setRefAnnotation(this);
1219  kRefAt.setName(Constants.KB_REF_ATT_NAME);
1220  kRefAt.setEntityType(this.getAnnotType().getName());
1221  Boolean nameSet = false;
1222  Boolean uriSet = false; // was URI set?
1223  Boolean vrSet = false;
1224  Boolean desSet = false;
1225  while (attribIt.hasNext()) {
1226  BaseAttribute tmpAttrib = attribIt.next();
1227  Boolean processed = false; // was attribute processed?
1228  if (!AttributeManager.hasAttributeRightInstance(tmpAttrib)) {
1229  tmpAttrib = AttributeManager.changeAttributeInstance(tmpAttrib);
1230  }
1231  if (tmpAttrib.getName().equalsIgnoreCase(Localisation.getKBStr(langNum, Localisation.KB_ARTWORK_NAME))) {
1232  if (tmpAttrib.getStringValue() != null && !nameSet) {
1233  kRefAt.setEntityName(tmpAttrib.getStringValue());
1234  nameSet = true;
1235  processed = true;
1236  }
1237  } else if (tmpAttrib.getName().equalsIgnoreCase(Localisation.getKBStr(langNum, Localisation.KB_DESCRIPTION))) {
1238  if (TextAttribute.class.isInstance(tmpAttrib)) {
1239  processed = true;
1240  if (tmpAttrib.getTextValue() != null) {
1241  if (desSet) {
1242  kRefAt.setDescription(kRefAt.getDescription() + tmpAttrib.getTextValue());
1243  } else {
1244  kRefAt.setDescription(tmpAttrib.getTextValue());
1245  desSet = true;
1246  }
1247  }
1248  } else if (StringAttribute.class.isInstance(tmpAttrib)) {
1249  processed = true;
1250  if (tmpAttrib.getStringValue() != null) {
1251  if (desSet) {
1252  kRefAt.setDescription(kRefAt.getDescription() + tmpAttrib.getStringValue());
1253  } else {
1254  kRefAt.setDescription(tmpAttrib.getStringValue());
1255  desSet = true;
1256  }
1257  }
1258  }
1259  } else if (tmpAttrib.getName().equalsIgnoreCase(Localisation.getKBStr(langNum, Localisation.KB_ENTITY_URI))) {
1260  if (tmpAttrib.getUri() != null && !uriSet) {
1261  kRefAt.setUri(tmpAttrib.getUri());
1262  uriSet = true;
1263  processed = true;
1264  }
1265  } else if (tmpAttrib.getName().equalsIgnoreCase(Localisation.getKBStr(langNum, Localisation.KB_VISUAL_REPRESENTATION))) {
1266  if (tmpAttrib.getUri() != null) {
1267  kRefAt.setEntityVisualURI(tmpAttrib.getUri());
1268  vrSet = true;
1269  processed = true;
1270  }
1271  }
1272  if (!processed) {
1273  String aName = tmpAttrib.getName();
1274  if (attFilter.contains(aName)) {
1275  continue;
1276  }
1277  if (tmpAttrib.getName().equalsIgnoreCase(Localisation.getKBStr(langNum, Localisation.KB_DISAMBIGUATION))) {
1278  tmpResult.append(tmpAttrib.toXMLStringV2());
1279  } else { // it is not disambiguation attribute
1280  EntityAdditionalAttribute adAt = tmpAttrib.toEntityAdditionalAttribute();
1281  if (adAt != null) {
1282  adAt.setRefEntityAttribute(kRefAt);
1283  kRefAt.getEntityAdditionalAttributes().add(adAt);
1284  } else {
1285  tmpResult.append(tmpAttrib.toXMLStringV2());
1286  }
1287  }
1288  } // if (!processed)
1289  } // while (attribIt.hasNext ...
1290  if (nameSet && desSet && uriSet) { // successfull conversion
1291  result.append(kRefAt.toXMLStringV2());
1292  result.append(tmpResult);
1293  } else { // unsuccessfull conversion
1294  attribIt = attributes.iterator();
1295  while (attribIt.hasNext()) {
1296  BaseAttribute tmpAttrib = attribIt.next();
1297  if (!AttributeManager.hasAttributeRightInstance(tmpAttrib)) {
1298  tmpAttrib = AttributeManager.changeAttributeInstance(tmpAttrib);
1299  }
1300  String aName = tmpAttrib.getName();
1301  if (attFilter.contains(aName)) {
1302  continue;
1303  }
1304  result.append(tmpAttrib.toXMLStringV2());
1305  }
1306  }
1307  return result;
1308  } // attributesToKBRefString()
1309 
1310  /**
1311  * Returns xpointers of all annotations fragments
1312  *
1313  * @return Returns xpointers of all annotations fragments
1314  */
1315  public String getFragmentXpointersV2(){
1316  String xpointers = "";
1317 
1318  Iterator<Fragment> fragIt = fragments.iterator();
1319  while(fragIt.hasNext()){
1320  xpointers += "#" + fragIt.next().getXpointerV2();
1321  }
1322 
1323  return xpointers;
1324  }
1325 
1326  /**
1327  * Returns serialized informations about annotation in XML
1328  *
1329  * @param proto11 If true, protocol version is greather then 1.0
1330  * @return Returns serialized informations about annotation in XML
1331  */
1332  public String toXMLString(boolean proto11) {
1333  return toXMLString(true, "", proto11, false);
1334  }
1335 
1336  /**
1337  * Returns serialized informations about annotation in XML
1338  *
1339  * @param annotTag Denotes whether wrapping tag annotation should be included
1340  * @param annotTagAttrs Attributes of created annotation tag
1341  * @param proto11 If true, protocol version is greather then 1.0
1342  * @param tmpIdForNested If true, nested annotations will have attribute tmpId
1343  * @return Returns serialized informations about annotation in XML
1344  */
1345  public String toXMLString(boolean annotTag, String annotTagAttrs, boolean proto11, boolean tmpIdForNested) {
1346  String authorAttr = "";
1347  if (authorName != null) {
1348  authorAttr = authorAttr + " name=\"" + authorName + "\"";
1349  }
1350  if (authorAddress != null) {
1351  authorAttr = authorAttr + " address=\"" + authorAddress + "\"";
1352  }
1353  String aboutStr = "";
1354  if (id != null) {
1355  aboutStr = AppBean.getBaseAnnotUri() + id;
1356  }
1357  String tIdForD = "";
1358  if (tmpIdForNested && nestedInAnnot != null) {
1359  tIdForD = " tmpId=\"" + tmpId + "\"";
1360  }
1361  if (annotTag) {
1362  return "<annotation" + annotTagAttrs + ">"
1363  + "<rdf:Description" + tIdForD + " rdf:about=\"" + aboutStr + "\">"
1364  + "<rdf:type rdf:resource=\"" + annotType.getUri() + "\"/>"
1365  + "<a:dateTime rdf:value=\"" + Util.toRFC3339Date(created) + "\" />"
1366  + "<a:author id=\"" + authorIdStr + "\"" + authorAttr + "/>"
1367  + "<a:source rdf:resource=\"" + source + "\"/>"
1368  + fragmentsToXMLString()
1369  + "<a:content>"
1370  + "<![CDATA["
1371  + content
1372  + "]]>"
1373  + "</a:content>"
1374  + attributesToXMLString(proto11, tmpIdForNested)
1375  + "</rdf:Description>"
1376  + "</annotation>";
1377  }
1378  return "<rdf:Description" + tIdForD + " rdf:about=\"" + aboutStr + "\">"
1379  + "<rdf:type rdf:resource=\"" + annotType.getUri() + "\"/>"
1380  + "<a:dateTime rdf:value=\"" + Util.toRFC3339Date(created) + "\" />"
1381  + "<a:author id=\"" + authorIdStr + "\"" + authorAttr + "/>"
1382  + "<a:source rdf:resource=\"" + source + "\"/>"
1383  + fragmentsToXMLString()
1384  + "<a:content>"
1385  + "<![CDATA["
1386  + content
1387  + "]]>"
1388  + "</a:content>"
1389  + attributesToXMLString(proto11, tmpIdForNested)
1390  + "</rdf:Description>";
1391  } // toXMLString()
1392 
1393  /**
1394  * Returns serialized informations about annotated fragments in XML
1395  *
1396  * @return Returns serialized informations about annotated fragments in XML
1397  */
1398  public String fragmentsToXMLString() {
1399  String fragmentsString = "";
1400  Iterator<Fragment> fragIt = fragments.iterator();
1401  Fragment fr;
1402  while (fragIt.hasNext()) {
1403  fr = fragIt.next();
1404  fragmentsString += fr.toXMLString();
1405  }
1406  return fragmentsString;
1407  }
1408 
1409  /**
1410  * Returns serialized informations about annotation attributes in XML
1411  *
1412  * @param proto11 If true, protocol version is greather then 1.0
1413  * @param tmpIdForNested If true, nested annotations will have attribute tmpId
1414  * @return Returns serialized informations about annotation attributes in XML
1415  */
1416  public String attributesToXMLString(boolean proto11, boolean tmpIdForNested) {
1417  String attrString = "";
1418  Collections.sort(attributes);
1419  Iterator<BaseAttribute> attrIt = attributes.iterator();
1420  BaseAttribute attr;
1421  while (attrIt.hasNext()) {
1422  attr = attrIt.next();
1423  attrString += attr.toXMLString(proto11, tmpIdForNested, false);
1424  }
1425  return attrString;
1426  }
1427 
1428  /**
1429  * Creates escaped version of the provided textual data. It is used when
1430  * text to be sent to the SEC Store server contains special characters like
1431  * quotes and backslash. Method expects SEC Store server to store strings
1432  * enclosed in double quote. That's why double quote character needs to be
1433  * escaped and single quote not.
1434  */
1435  private String EscapeCharsToSend(String source) {
1436  String result = source;
1437  // string can have null value if suggestions type is not requested
1438  if (result != null) {
1439  result = result.replace("\\", "\\\\");
1440  result = result.replace("\"", "\\\"");
1441  }
1442  return result;
1443  } //EscapeChars()
1444 
1445  /**
1446  * Stores annotation data into the JSON string representation. String could be
1447  * processed on the SEC Store API server. Method stores IDs of referenced
1448  * structures, so when creating an object from this representation,
1449  * one must look up for structures by IDs.
1450  *
1451  * @return String representation of JSON Annotation data
1452  */
1453  public String toJsonString(Integer sOffset, Integer eOffset) {
1454  String retJson = "{\"startOffset\":";
1455  StringBuilder sb = new StringBuilder(retJson);
1456  // offsets
1457  sb.append(sOffset);
1458  sb.append(",\"endOffset\":");
1459  sb.append(eOffset);
1460  sb.append(",\"uri\":\"");
1461  // URI of the annotation
1462  sb.append(this.getURI());
1463  // path of the type of the annotation
1464  sb.append("\",\"annotTypePath\":\"");
1465  if (this.getAnnotType() != null) {
1466  String typeUri = this.getAnnotType().getUri();
1467  // remove server address and group number
1468  String strippedServer = typeUri.replace(AppBean.getBaseTypeUri(), "");
1469  String strippedGroup = strippedServer.replaceFirst("g[0-9]+\\/", "");
1470  sb.append(strippedGroup);
1471  }
1472  sb.append("\",\"typeUriInOntology\":\"");
1473  if (this.getAnnotType() != null) {
1474  sb.append(this.getAnnotType().getUriInOntology());
1475  }
1476  // list of groups that author belongs to
1477  sb.append("\",\"authorGroups\":[");
1478  for (Iterator<UserGroup> ug = this.user.groups.iterator(); ug.hasNext();) {
1479  UserGroup nextUG = ug.next();
1480  sb.append("{\"uri\":\"");
1481  // URI of the group
1482  sb.append(nextUG.getUri());
1483  // name of the group
1484  sb.append("\",\"name\":\"");
1485  sb.append(nextUG.getName());
1486  sb.append("\"},");
1487  }
1488  sb.deleteCharAt(sb.length()-1);
1489  sb.append("],\"annotTypeGroup\":\"");
1490  if (this.getAnnotType() != null && this.getAnnotType().getGroup() != null) {
1491  sb.append(this.getAnnotType().getGroup().getUri());
1492  }
1493  sb.append("\",\"sourceUri\":\"");
1494  // URI of the document which the annotation belongs to
1495  sb.append(this.sourceDocument.getUri());
1496  sb.append("\",\"content\":\"");
1497  // content of the annotation
1498  sb.append(EscapeCharsToSend(this.content));
1499  sb.append("\",\"annoText\":\"");
1500  // text that has been annotated
1501  for (Iterator<Fragment> frIt = this.fragments.iterator(); frIt.hasNext();) {
1502  sb.append(EscapeCharsToSend(frIt.next().getAnnotatedText()));
1503  }
1504  sb.append("\",\"attributes\":[");
1505  if (this.attributes != null && !this.attributes.isEmpty()) {
1506  // a list of annotation's attributes
1507  for (Iterator<BaseAttribute> atIt = this.attributes.iterator(); atIt.hasNext();) {
1508  BaseAttribute att = atIt.next();
1509  sb.append(att.toJSONString());
1510  sb.append(",");
1511  // if attribute is annotation, set ID of parent annotation as nestedIn
1512  if (att.getSimpleType().equals("NestedAnnotation") && att.getNestedAnnotation() != null) {
1513  att.getNestedAnnotation().setNestedIn(this.id.toString());
1514  }
1515  }
1516  sb.deleteCharAt(sb.length()-1);
1517  }
1518  sb.append("],\"nestedIn\":\"");
1519  if (this.getNestedInAnnot() != null) {
1520  sb.append(this.getNestedInAnnot().getURI());
1521  }
1522  else {
1523  sb.append("null");
1524  }
1525  sb.append("\"}");
1526  return sb.toString();
1527  } // toJsonString()
1528 
1529  public String getNewAnnotMsg(){
1530  StringBuilder retStr = new StringBuilder();
1531  retStr.append("<annotation tempUri=\"");
1532  retStr.append(AppBean.getBaseAnnotUri());
1533  retStr.append("temp/");
1534  retStr.append(tmpId);
1535  retStr.append("\" servUri=\"");
1536  retStr.append(AppBean.getBaseAnnotUri());
1537  retStr.append("serv/");
1538  retStr.append(id.toString());
1539  retStr.append("/>");
1540  return retStr.toString();
1541  }
1542 
1543  /**
1544  * Gets tmpId of annotation
1545  *
1546  * @return Returns tmpId of annotation
1547  */
1548  public String getTmpId() {
1549  return this.tmpId;
1550  }
1551 
1552  /**
1553  * Sets tmpId of annotation
1554  * @param tmpId New tmpId
1555  */
1556  public void setTmpId(String tmpId) {
1557  this.tmpId = tmpId;
1558  }
1559 
1560  /**
1561  * Returns a list containing IDs of annotations that links this annotation
1562  *
1563  * @return list of integer IDs
1564  */
1565  public List<Integer> getLinkedByBeforeRemove() {
1566  return this.linkedByBeforeRemove;
1567  }
1568 
1569  /**
1570  * Inserts ID of annotation that links this particular annotation to the list
1571  *
1572  * @param id ID of annotation that links this particular annotation
1573  */
1574  public void addLinkedByBeforeRemove(Integer id) {
1575  // create list only in case that it is needed
1576  if (this.linkedByBeforeRemove == null) {
1577  this.linkedByBeforeRemove = new ArrayList<Integer>();
1578  }
1579  // prevent duplicities
1580  if (!this.linkedByBeforeRemove.contains(id)) {
1581  this.linkedByBeforeRemove.add(id);
1582  }
1583  }
1584 
1585  /**
1586  * Clears the list containing ID. It should be used after the remove message
1587  * for this particular annotation has been created.
1588  */
1590  this.linkedByBeforeRemove.clear();
1591  }
1592 
1593  /**
1594  * Adds all IDs of linking annotations.
1595  *
1596  * @param IDs list of IDs of annotations that contain attribute linking this particular annotation
1597  */
1598  public void addAllLinkedByBeforeRemove(List<Integer> IDs) {
1599  if(this.linkedByBeforeRemove == null){
1600  this.linkedByBeforeRemove = new ArrayList<Integer>();
1601  }
1602  this.linkedByBeforeRemove.addAll(IDs);
1603  }
1604 
1605 } // class Annotation
void addAllLinkedByBeforeRemove(List< Integer > IDs)
void setSourceDocumentId(Integer sourceDocumentId)
Utility functions for document linearization.
Definition: Linearizer.java:40
StringBuilder attributesToKBRefString(ArrayList< String > attFilter, int langNum)
Class representing attribute of type String..
static final ArrayList< String > FORBIDDEN_ENTITY_TYPES
Definition: Constants.java:432
Class representing annotated copy of document.
void setNestedInAnnot(Annotation nestedInAnnot)
Singleton for storing global variables.
Definition: AppBean.java:47
static String escapeForXml(String str)
Definition: Util.java:380
Class providing access to available matchers.
Class representing attribute of type Text.
Annotation(AnnotType annotType, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content, Annotation nestedInAnnot)
String toXMLStringV2(ArrayList< String > attFilter, int langNum, Boolean KBRefMode)
Class representing vocabulary entity attribute.
String toXMLString(boolean annotTag, String annotTagAttrs, boolean proto11, boolean tmpIdForNested)
Class representing user group.
Definition: UserGroup.java:47
void setAttributes(ArrayList< BaseAttribute > attributes)
void setSourceDocument(AnnotDocument sourceDocument)
Annotation(Integer id, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content, String nestedIn)
boolean equals(Object object, boolean noLinked)
String attributesToXMLString(boolean proto11, boolean tmpIdForNested)
Base class representing attribute of annotation.
Class representing type of annotation.
Definition: AnnotType.java:58
Class representing user.
Definition: User.java:51
Annotation(AnnotType annotType, Date created, String authorIdStr, String authorName, String authorAddress, AnnotDocument sourceDocument, String content)
String toSXMLString(boolean addSpaces, boolean addCreated)
void addAttribute(BaseAttribute attribute)
Class attribute manager provides a way how to create new attributes.
Class representing suggestion of annotation.
Definition: Suggestion.java:87
boolean contentEquals(Object obj, boolean withCreated, boolean noLinked)
Class responsible for localised strings.
void setFragments(ArrayList< Fragment > fragments)
Utility class (manipulates RFC 3339 dates)
Definition: Util.java:29
Class representing annotated fragment.
Definition: Fragment.java:48
String toJsonString(Integer sOffset, Integer eOffset)
static String toRFC3339Date(Date date)
Definition: Util.java:208