4A Server -  2.0
 All Classes Namespaces Files Functions Variables Enumerator
StoryscopeInterfaceSender.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: StoryscopeInterfaceSender.java
5  * Description: Class represent thread of Storyscope Interface that sends
6  * messages to StoryScopes
7  */
8 
9 /**
10  * @file StoryscopeInterfaceSender.java
11  *
12  * @brief Class represent thread of Storyscope Interface that sends messages to StoryScopes
13  */
14 
15 package cz.vutbr.fit.knot.annotations.modules.StoryscopeInterface;
16 
32 import java.io.BufferedReader;
33 import java.io.InputStreamReader;
34 import java.io.OutputStreamWriter;
35 import java.net.URL;
36 import java.net.URLConnection;
37 import java.net.URLEncoder;
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43 import org.w3c.dom.Document;
44 
45 /**
46  * Class that represents a thread that sends annotations from all documents
47  * according to the rules composed of Subscribed and unsubscribed sources, types
48  * and users.
49  *
50  * @brief Class represent thread of Storyscope Interface that sends messages to StoryScopes
51  * @author Martin Petr (xpetrm05)
52  */
53 public class StoryscopeInterfaceSender extends Thread {
54 
55  /** List of avaibel StoryScopes */
56  private List<StoryScope> storyScopes;
57  /** Object with informations about current request */
59  /** Array of added annotations to send to Storyscope */
60  ArrayList<Annotation> addedAnnotations;
61  /** Array of edited annotations to send to Storyscope */
62  ArrayList<Annotation> editedAnnotations;
63  /** Array of removed annotations to send to Storyscope */
64  ArrayList<Annotation> removedAnnotations;
65  /** Indicates if this code will be started as module (in therad) or not */
66  boolean runAsModule;
67  /** Pattern of response from StoryScope*/
68  private static final String answerTemplate = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ok/>";
69 
70  /**
71  * Constructor
72  *
73  * @param requestInfo informations about current request
74  */
76  super("StoryscopeInterfaceSender");
77  runAsModule = true;
78  this.requestInfo = requestInfo;
79  addedAnnotations = requestInfo.getFlier().getAddedAnnotations();
80  if(addedAnnotations == null){
81  addedAnnotations = new ArrayList<Annotation>();
82  }
83 
84  editedAnnotations = requestInfo.getFlier().getEditedAnnotations();
85  if(editedAnnotations == null){
86  editedAnnotations = new ArrayList<Annotation>();
87  }
88 
89  removedAnnotations = requestInfo.getFlier().getRemovedAnnotations();
90  if(removedAnnotations == null){
91  removedAnnotations = new ArrayList<Annotation>();
92  }
93  }
94 
95  /**
96  * Constructor (not run in thread).
97  *
98  * @param name of thread
99  */
100  public StoryscopeInterfaceSender(String name) {
101  super(name);
102  runAsModule = false;
103  addedAnnotations = new ArrayList<Annotation>();
104  editedAnnotations = new ArrayList<Annotation>();
105  removedAnnotations = new ArrayList<Annotation>();
106  }
107 
108  /**
109  * Gets array of added annotations to send to Storyscope
110  *
111  * @return array of added annotations
112  */
113  public ArrayList<Annotation> getAddedAnnotations() {
114  return addedAnnotations;
115  }
116 
117  /**
118  * Sets array of added annotations to send to Storyscope
119  *
120  * @param addedAnnotations array of added annotations to send to Storyscope
121  */
122  public void setAddedAnnotations(ArrayList<Annotation> addedAnnotations) {
123  this.addedAnnotations = addedAnnotations;
124  }
125 
126  /**
127  * Gets array of edited annotations to send to Storyscope
128  *
129  * @return array of edited annotations
130  */
131  public ArrayList<Annotation> getEditedAnnotations() {
132  return editedAnnotations;
133  }
134 
135  /**
136  * Sets array of edited annotations to send to Storyscope
137  *
138  * @param editedAnnotations array of edited annotations to send to Storyscope
139  */
140  public void setEditedAnnotations(ArrayList<Annotation> editedAnnotations) {
141  this.editedAnnotations = editedAnnotations;
142  }
143 
144  /**
145  * Gets array of removed annotations to send to Storyscope
146  *
147  * @return array of removed annotations
148  */
149  public ArrayList<Annotation> getRemovedAnnotations() {
150  return removedAnnotations;
151  }
152 
153  /**
154  * Sets array of removed annotations to send to Storyscope
155  *
156  * @param removedAnnotations array of removed annotations to send to Storyscope
157  */
158  public void setRemovedAnnotations(ArrayList<Annotation> removedAnnotations) {
159  this.removedAnnotations = removedAnnotations;
160  }
161 
162  /**
163  * Method locks documents for read and run main method.
164  *
165  */
166  @Override
167  public void run(){
168  //lock document for change
169  if (requestInfo.getSession() == null || requestInfo.getSession().getSyncDocument() == null) {
170  return;
171  }
172 
173  AnnotDocument doc = requestInfo.getSession().getSyncDocument();
174 
175  if(doc != null){
176  while(true){
177  if(AppBean.getLockMaster().getDocumentLock(doc.getId()).lockForRead()){
178  break;
179  }
180  }
181  }
182 
183  try{
184  startModule();
185  }
186 
187  catch(Exception ex){
188  // unlock document for change
189  if(doc != null){
190  AppBean.getLockMaster().getDocumentLock(doc.getId()).unlockForRead();
191  }
192  }
193 
194  finally{
195  // unlock document for change
196  if(doc != null){
197  AppBean.getLockMaster().getDocumentLock(doc.getId()).unlockForRead();
198  }
199  }
200  }
201 
202  /**
203  * Method check added, edited and deleted annotations and set them to configured
204  * StoryScopes. If is StoryScope unreachable, method save its messages and
205  * send them when will be reachable.
206  */
207  void startModule(){
208  //body of new thread
209  @SuppressWarnings("unchecked")
210  List<StoryScope> tmpList = AppBean.getPersistenceManager().getEntitiesByName("StoryScope");
211  storyScopes = tmpList;
212 
213  if(storyScopes != null){
214  Iterator<StoryScope> ssListIterator = storyScopes.iterator();
215 
216  while(ssListIterator.hasNext()){ // for each StoryScope
217  StoryScope actualStoryScope = ssListIterator.next();
218  ArrayList<SubscribedSource> subscribedList = actualStoryScope.getSubscribedList();
219  ArrayList<SubscribedSource> unsubscribedList = actualStoryScope.getUnsubscribedList();
220 
221  //processing annotations that was added
222  ArrayList<Annotation> refusedAnnotations = new ArrayList<Annotation>();
223  ArrayList<Annotation> acceptedAnnotations = new ArrayList<Annotation>();
224  Iterator addAnnotIterator = addedAnnotations.iterator();
225  //go trough all added annotations
226  while(addAnnotIterator.hasNext()){
227  Annotation actualAnnotation = (Annotation)addAnnotIterator.next();
228  //and test they for subscription
229  if(isSubscribed(actualAnnotation,unsubscribedList,subscribedList, CoreFuncModule.getUserSources(actualAnnotation.getUser()))){
230  acceptedAnnotations.add(actualAnnotation);
231  }else{
232  refusedAnnotations.add(actualAnnotation);
233  }
234  }
235 
236  //for unaccdepted and accepted annotation must be checked if they are link with other annotation
237  acceptedAnnotations = getRelatedAnnotations(acceptedAnnotations,refusedAnnotations,subscribedList,unsubscribedList);
238  ArrayList<String> addMessage = new ArrayList<String>();
239  Iterator<Annotation> acceptedIterator = acceptedAnnotations.iterator();
240  while(acceptedIterator.hasNext())
241  {
242  addMessage.add(AnnotationToXMLStringL(acceptedIterator.next(), requestInfo.getSession().getParsedSyncDocument()));
243  }
244 
245  //processing annotations that was changed or auto updated
246  //this part of code add auto updated annotations
247  //at first checks if flier have some auto updated anotations
248  if(runAsModule && requestInfo.getFlier().getAutoUpdatedAnnotations()!=null){
249  //if is edited annotations array list empty
250  if(editedAnnotations == null){
251  //simply add all auto updated annotations
252  editedAnnotations = requestInfo.getFlier().getAutoUpdatedAnnotations();
253  }else{
254  //if edited annotations array list have some annotations
255  Iterator<Annotation> autoUpdatedIter = requestInfo.getFlier().getAutoUpdatedAnnotations().iterator();
256 
257  //check if edited annotations don't contains same annotation that is in auto updated annotations array list
258  while(autoUpdatedIter.hasNext()){
259  Annotation actualAnnotation = autoUpdatedIter.next();
260  if(!editedAnnotations.contains(actualAnnotation)){
261  //add only different annotations
262  editedAnnotations.add(actualAnnotation);
263  }
264  }
265  }
266  }
267 
268  refusedAnnotations = new ArrayList<Annotation>();
269  acceptedAnnotations = new ArrayList<Annotation>();
270  Iterator editedAnnotIterator = editedAnnotations.iterator();
271  //go trough all changed annotations
272  while(editedAnnotIterator.hasNext()){
273  Annotation actualAnnotation = (Annotation)editedAnnotIterator.next();
274  //and test they for subscription
275  if(isSubscribed(actualAnnotation,unsubscribedList,subscribedList,CoreFuncModule.getUserSources(actualAnnotation.getUser()))){
276  acceptedAnnotations.add(actualAnnotation);
277  }else{
278  refusedAnnotations.add(actualAnnotation);
279  }
280  }
281 
282  //for unaccdepted and accepted annotation must be checked if they are link with other annotation
283  acceptedAnnotations = getRelatedAnnotations(acceptedAnnotations,refusedAnnotations,subscribedList,unsubscribedList);
284  ArrayList<String> editedMessage = new ArrayList<String>();
285  acceptedIterator = acceptedAnnotations.iterator();
286  while(acceptedIterator.hasNext())
287  {
288  editedMessage.add(AnnotationToXMLStringL(acceptedIterator.next(), requestInfo.getSession().getParsedSyncDocument()));
289  }
290 
291  //processing annotations that was deleted
292  refusedAnnotations = new ArrayList<Annotation>();
293  acceptedAnnotations = new ArrayList<Annotation>();
294  Iterator removedAnnotIterator = removedAnnotations.iterator();
295  //go trough all deleted annotations
296  while(removedAnnotIterator.hasNext()){
297  Annotation actualAnnotation = (Annotation)removedAnnotIterator.next();
298  //and test they for subscription
299  if(isSubscribed(actualAnnotation,unsubscribedList,subscribedList,CoreFuncModule.getUserSources(actualAnnotation.getUser()))){
300  acceptedAnnotations.add(actualAnnotation);
301  }else{
302  refusedAnnotations.add(actualAnnotation);
303  }
304  }
305 
306  //for unaccdepted and accepted annotation must be checked if they are link with other annotation
307  acceptedAnnotations = getRelatedAnnotations(acceptedAnnotations,refusedAnnotations,subscribedList,unsubscribedList);
308  ArrayList<String> removedMessage = new ArrayList<String>();
309  acceptedIterator = acceptedAnnotations.iterator();
310  while(acceptedIterator.hasNext())
311  {
312  removedMessage.add(AnnotationToXMLStringL(acceptedIterator.next(), requestInfo.getSession().getParsedSyncDocument()));
313  }
314 
315  //if there are messages for sent
316  if(!addMessage.isEmpty() || !editedMessage.isEmpty() || !removedMessage.isEmpty())
317  {
318  String message = "<add>" + actualStoryScope.getMessagesAdd() + StoryScope.messagesToString(addMessage) + "</add>"
319  + "<change>" + actualStoryScope.getMessagesChange() + StoryScope.messagesToString(editedMessage) + "</change>"
320  + "<remove>" + actualStoryScope.getMessagesDelete() + StoryScope.messagesToString(removedMessage) + "</remove>";
321 
322  String data = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
323  + "<messages xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
324  + " xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\""
325  + " xmlns:a=\"http://knot.fit.vutbr.cz/annotations/AnnotXMLSchema\">\n"
326  + "<annotations>"
327  + message
328  + "</annotations>"
329  + "</messages>";
330  //try to send message for actual StroySpace
331  if(!sendAndCheck(actualStoryScope, data)){
332  //new annotations must be sent wether error occurs
333  actualStoryScope.addSavedMessages(addMessage, SavedMessage.MESSAGE_ADD);
334  actualStoryScope.addSavedMessages(editedMessage, SavedMessage.MESSAGE_CHANGE);
335  actualStoryScope.addSavedMessages(removedMessage, SavedMessage.MESSAGE_DELETE);
336  }else{
337  actualStoryScope.deleteMessages();
338  }
339  }
340  } // // for each StoryScope
341  } // if(storyScopes != null
342  } // startModule()
343 
344  /**
345  * Method sends a message for each StoryScope in list and check if the StoryScope
346  * sent correct answer.
347  *
348  * @param storyScope StoryScopes whose message will be sent.
349  * @param data Data to send
350  */
351  private boolean sendAndCheck(StoryScope storyScope, String data){
352  String answer = new String();
353 
354  try{
355  String postMessage = "xml=" + URLEncoder.encode(data,"UTF-8");
356 
357  URL clientUrl = new URL(storyScope.getClientURL());
358  URLConnection clientConnection = clientUrl.openConnection();
359  clientConnection.setDoOutput(true);
360 
361  OutputStreamWriter dataWriter = new OutputStreamWriter(clientConnection.getOutputStream());
362  dataWriter.write(postMessage);
363  dataWriter.close();
364 
365  BufferedReader recivedData = new BufferedReader(new InputStreamReader(clientConnection.getInputStream()));
366  String line;
367  while ((line = recivedData.readLine()) != null) {
368  answer += line;
369  }
370  recivedData.close();
371  }
372 
373  catch(Exception e){
375  String msg = "Unable to send data to StoryScope with name: " + storyScope.getName() + ".";
376  Logger.getLogger(StoryscopeInterfaceSender.class.getName()).log(Level.SEVERE, msg);
377  return false;
378  }
379  }
380 
381  if(!answer.equalsIgnoreCase(answerTemplate)){
383  String msg = "A confirmation message from StoryScope with name: " + storyScope.getName() + " not match. Message content:" + answer;
384  Logger.getLogger(StoryscopeInterfaceSender.class.getName()).log(Level.SEVERE, msg);
385  return false;
386  }
387  }
388 
389  return true;
390  } // sendAndCheck()
391 
392  /**
393  * Method finds every rule for all given annotation's type ancestors and returns
394  * if is subscribed or unsubscribed.
395  *
396  * @param rootType type where will checking begin
397  * @param annot annotation that is checked
398  * @param unsubscribedSources unsubscribed sources for current user
399  * @param subscribedSources subscribed sources for current user
400  * @param sources sources for current user
401  * @param unsubResult list of finded unsubscribed rules
402  * @param subResult list of finded subscribed files
403  * @return value that represent if is current annotation subscribed unsubscribed or method don't find any rule
404  */
405  private int checkBranch(AnnotType rootType, Annotation annot, ArrayList<SubscribedSource> unsubscribedSources,
406  ArrayList<SubscribedSource> subscribedSources,ArrayList<String> sources,ArrayList<SubscribedSource> unsubResult,
407  ArrayList<SubscribedSource> subResult){ //sorry for this :-(
408 
409  AnnotType actualType = rootType;
410 
411  while(actualType != null) //climb tree of types from nod to root
412  {
413  int ancestorsCount = actualType.getAncestorTypes().size();
414 
415  if(ancestorsCount <= 1){
416  // check if is current type type of annotation in unsubscribed list
417  unsubResult.clear();
418  unsubResult.addAll(EditorSession.listOfMatches(unsubscribedSources,annot,actualType,sources));
419 
420  // or in subscribed list
421  subResult.clear();
422  subResult.addAll(EditorSession.listOfMatches(subscribedSources,annot,actualType,sources));
423 
424  if(!subResult.isEmpty() && EditorSession.containTypeRule(subResult)){
425  return Constants.SUBSCRIBED; // if was type found in subscribed then return true
426  }else{
427  if(!unsubResult.isEmpty() && EditorSession.containTypeRule(unsubResult)){
428  return Constants.UNSUBSCRIBED; // if was type of annotation found in unsubscribed then return false
429  }
430  }
431 
432  actualType = actualType.getAncestorType();
433  }else{
434  Iterator<AnnotType> typeIt = actualType.getAncestorTypes().iterator();
435  int resultsArray[] = new int [ancestorsCount];
436  boolean unsubscribedOccur = false;
437 
438  for(int i = 0;typeIt.hasNext();i++){
439  resultsArray[i] = checkBranch(typeIt.next(),annot,unsubscribedSources,subscribedSources,sources,unsubResult,subResult);
440  if(resultsArray[i] == Constants.SUBSCRIBED) return Constants.SUBSCRIBED;
441  if(resultsArray[i] == Constants.UNSUBSCRIBED) unsubscribedOccur = true;
442  }
443 
444  if(unsubscribedOccur) return Constants.UNSUBSCRIBED;
445  else return Constants.NOTHING;
446  }
447  }
448  return Constants.NOTHING;
449  }
450 
451  /**
452  * Method will check if the given annotation meets the criteria for sending to
453  * StoryScope
454  *
455  * @param annot Checked annotation
456  * @param unsubscribedSources list of unsubscribed sources
457  * @param subscribedSources list of subscribed sources
458  * @param sources List of sources to which annotation belongs to
459  * @return If annotation matches to subscriptions, returns true, false otherwise
460  */
461  private boolean isSubscribed(Annotation annot,ArrayList<SubscribedSource> unsubscribedSources, ArrayList<SubscribedSource> subscribedSources, ArrayList<String> sources) {
462 
463  ArrayList<SubscribedSource> unsubResult = new ArrayList<SubscribedSource>();
464  ArrayList<SubscribedSource> subResult = new ArrayList<SubscribedSource>();
465 
466  switch(checkBranch(annot.getAnnotType(),annot,unsubscribedSources,subscribedSources,sources,unsubResult,subResult)){
467  case Constants.SUBSCRIBED: return true;
468  case Constants.UNSUBSCRIBED: return false;
469  default:
470  }
471 
472  //if there occured only hungry subscriptions
473 
474  if(!subResult.isEmpty() || !unsubResult.isEmpty())
475  {
476  if(EditorSession.containUserRule(subResult)){
477  return true;
478  }
479  if(EditorSession.containUserRule(unsubResult)){
480  return false;
481  }
482  if(EditorSession.containSourceRule(subResult)){
483  return true;
484  }
485  if(EditorSession.containSourceRule(unsubResult)){
486  return false;
487  }
488  }
489 
490  return false;
491  } // isSubscribed()
492 
493  /**
494  * Method returns all linked annotations of this annotation.
495  *
496  * @param annot annotation which will be processed
497  * @return list of annotations that are linked with this annotation
498  */
499  private ArrayList<Annotation> getLinkedAnnotations(Annotation annot){
500  ArrayList<Annotation> innerAnnotationList = new ArrayList<Annotation>();
501  Iterator <BaseAttribute> attrIt = annot.getAttributes().iterator();
502 
503  while(attrIt.hasNext()){
504  BaseAttribute attrTmp = attrIt.next();
505  if(attrTmp instanceof LinkedAnnotationAttribute)
506  {
507  //here are only linked annotations
508  LinkedAnnotationAttribute linkedAttr = (LinkedAnnotationAttribute)attrTmp;
509  innerAnnotationList.add((Annotation)linkedAttr.getValue());
510  }
511  }
512 
513  return innerAnnotationList;
514  }
515 
516  /**
517  * Method returns all annotations that are link annotation given as parameter.
518  *
519  * @param annot annotation which will be processed
520  * @return list of annotations that links this anotation
521  */
522  private ArrayList<Annotation> getLinkedAnnotationsDB(Annotation annot){
523  ArrayList<Annotation> innerAnnotationList = new ArrayList<Annotation>();
524  Object[] params = {"linked",annot.getId()};
525  @SuppressWarnings("unchecked")
526  List <LinkedAnnotationAttribute> attrList = AppBean.getPersistenceManager().queryDB("Attribute.findByLinked", params);
527  if(attrList != null)
528  {
529  Iterator <LinkedAnnotationAttribute> attrIt = attrList.iterator();
530 
531  while(attrIt.hasNext()){
532  LinkedAnnotationAttribute linkedAttr = attrIt.next();
533  Annotation dbAnnot = (Annotation)AppBean.getPersistenceManager().getEntityById("Annotation", linkedAttr.getAnnotation());
534  if(dbAnnot != null){
535  innerAnnotationList.add(dbAnnot);
536  }
537  }
538  }
539  return innerAnnotationList;
540  }
541 
542  /**
543  * Method check if annotation have any linked type parameter and all this parameters
544  * add to list with secondaryAnnotList. But check if isn't inside main or secondary
545  * annotations list before add it.
546  *
547  * @param mainAnnotList array list of approved annotations
548  * @param secondaryAnnotList secondary list of approved annotations
549  * @param annot annotatihon thats linked type attributes will be add to list
550  * @return return list thats contain secodary annotation list and linked type annotations from annotation
551  */
552  private ArrayList<Annotation> decomposeLinked(ArrayList<Annotation> mainAnnotList, ArrayList<Annotation> secondaryAnnotList, Annotation annot){
553  Iterator<Annotation> innerIt = getLinkedAnnotations(annot).iterator();
554 
555  found : while(innerIt.hasNext()){
556  Annotation actualAnnot = innerIt.next();
557  //as first, go trough main annotations (approved annotations)
558  Iterator<Annotation> mainIt = mainAnnotList.iterator();
559  while(mainIt.hasNext()){
560  //check if current annotation from linked is in main annotations list
561  Annotation approvedAnnot = mainIt.next();
562  if(approvedAnnot.getId() == actualAnnot.getId()){
563  continue found;
564  }
565  }
566 
567  //as second, go trough secondary annotations (approved annotations)
568  Iterator<Annotation> secondIt = secondaryAnnotList.iterator();
569  while(secondIt.hasNext()){
570  //check if current annotation from linked is in secondary annotations list
571  Annotation approvedAnnot = secondIt.next();
572  if(approvedAnnot.getId() == actualAnnot.getId()){
573  continue found;
574  }
575  }
576  secondaryAnnotList.add(actualAnnot);
577  }
578 
579  return secondaryAnnotList;
580  }
581 
582  /**
583  * Method checks if approved and unapproved annotations have linked type attributes
584  * when there are any, add annotations that are linked with approved or if they are
585  * subscribed.
586  *
587  * @param approvedAnnot annotations that are approved (they are subscribed)
588  * @param unapprovedAnnot annotations that are unapproved (others annotations)
589  * @param subscribed list of subscribed sources for current StoryScope
590  * @param unsubscribed list of unsubscribed sources for current StoryScope
591  * @return approved annotations and added annotations together in one list
592  */
593  private ArrayList<Annotation> getRelatedAnnotations(ArrayList<Annotation> approvedAnnot,
594  ArrayList<Annotation> unapprovedAnnot,
595  ArrayList<SubscribedSource> subscribed,
596  ArrayList<SubscribedSource> unsubscribed){
597 
598  ArrayList<Annotation> secondaryApproved = getRelatedAnnots(approvedAnnot,unapprovedAnnot,subscribed,unsubscribed);
599  Iterator<Annotation> secApprovedIt = secondaryApproved.iterator();
600  ArrayList<Annotation> addedAnnotations = new ArrayList<Annotation>();
601 
602  while(secApprovedIt.hasNext()){
603  //annotations that will be tested will be in this list
604  ArrayList<Annotation> openList = new ArrayList<Annotation>();
605  //there will be annotations after test
606  ArrayList<Annotation> closeList = new ArrayList<Annotation>();
607  openList.add(secApprovedIt.next());
608  while(!openList.isEmpty()){
609  Annotation actualAnnot = openList.remove(0);
610  closeList.add(actualAnnot);
611 
612  ArrayList<Annotation> links = getLinkedAnnotations(actualAnnot);
613  if(links != null) links.addAll(getLinkedAnnotationsDB(actualAnnot));
614  else links = getLinkedAnnotationsDB(actualAnnot);
615  if(links != null){
616  Iterator<Annotation> linksIt = links.iterator();
617  while(linksIt.hasNext()){
618  Annotation actualLink = linksIt.next();
619  if(!openList.contains(actualLink) && !closeList.contains(actualLink)){
620  openList.add(actualLink);
621  if(!addedAnnotations.contains(actualLink) && !approvedAnnot.contains(actualLink))
622  {
623  addedAnnotations.add(actualLink);
624  }
625  }
626  }
627  }
628 
629  }
630  }
631 
632  if(approvedAnnot == null){
633  return addedAnnotations;
634  }
635 
636  approvedAnnot.addAll(addedAnnotations);
637  return approvedAnnot;
638  }
639 
640  /**
641  * Method gets related annotations that links given annotation.
642  *
643  * @param approvedAnnot list od approved annotations
644  * @param unapprovedAnnot list of unapproved annotations
645  * @param subscribed subecribed rules
646  * @param unsubscribed unsubscribed rules
647  * @return list of realted annotations
648  */
649  public ArrayList<Annotation> getRelatedAnnots(ArrayList<Annotation> approvedAnnot,
650  ArrayList<Annotation> unapprovedAnnot,
651  ArrayList<SubscribedSource> subscribed,
652  ArrayList<SubscribedSource> unsubscribed) {
653  ArrayList<Annotation> result = new ArrayList<Annotation>();
654  Iterator<Annotation> unapprovedIt = unapprovedAnnot.iterator();
655 
656  while (unapprovedIt.hasNext()) {
657  //annotations that will be tested will be in this list
658  ArrayList<Annotation> openList = new ArrayList<Annotation>();
659  //there will be annotations after test
660  ArrayList<Annotation> closeList = new ArrayList<Annotation>();
661  openList.add(unapprovedIt.next());
662 
663  while (!openList.isEmpty()) {
664  Annotation actualAnnot = openList.remove(0);
665  closeList.add(actualAnnot);
666 
667  if (isSubscribed(actualAnnot, unsubscribed, subscribed, CoreFuncModule.getUserSources(actualAnnot.getUser()))) {
668  result.add(actualAnnot);
669  } else {
670  //get annotations which linked actual annotation, then get annotatinos that are not in close list then in open list
671  //on the end is in annotForAdd list only annotations that linked at actual annotation and they ar not in close and open list
672  ArrayList<Annotation> annotForAdd = CoreFuncModule.getDifference(CoreFuncModule.getDifference(CoreFuncModule.getLinkedAnnotationsDB(actualAnnot), closeList), openList);
673  openList.addAll(annotForAdd);
674  }
675  }
676  }
677 
678  if(approvedAnnot == null){
679  return result;
680  }
681 
682  approvedAnnot.addAll(result);
683  return approvedAnnot;
684  }
685 
686  /**
687  * Method finds all ancestors of type annotation of annotation given as attribute.
688  *
689  * @param annot annotation which will be processed
690  * @return string with uri of all ancestors of annotation's type
691  */
693  StringBuilder result = new StringBuilder();
694  ArrayList<AnnotType> openList = new ArrayList<AnnotType>();
695  ArrayList<AnnotType> closeList = new ArrayList<AnnotType>();
696 
697  openList.add(annot.getAnnotType());
698  while(!openList.isEmpty()){
699  AnnotType actualAnnot = openList.remove(0);
700  if(!closeList.contains(actualAnnot)){
701  closeList.add(actualAnnot);
702  result.append("<ancestorType uri=\"").append(actualAnnot.getUri()).append("\"/>");
703  openList.addAll(actualAnnot.getAncestorTypes());
704  }
705  }
706 
707  return result.toString();
708  }
709 
710  /**
711  * Info:
712  * Methods below are copied from Annotations, they are modified, because modifed
713  * protocol is used between Storyscope Interface and SEC Client.
714  */
715 
716  /**
717  * Returns serialized and linearized informations about annotation in XML
718  *
719  * @param annot annotation that will be represented by XML
720  * @param doc anotated document
721  * @return Returns serialized informations about annotation in XML
722  */
723  public String AnnotationToXMLStringL(Annotation annot,Document doc) {
724  String authorAttr = "";
725  if (annot.getAuthorName() != null) {
726  authorAttr = authorAttr + " name=\"" + annot.getAuthorName() + "\"";
727  }
728  if (annot.getAuthorAddress() != null) {
729  authorAttr = authorAttr + " address=\"" + annot.getAuthorAddress() + "\"";
730  }
731  String aboutStr = "";
732  if (annot.getId() != null) {
733  aboutStr = AppBean.getBaseAnnotUri() + annot.getId();
734  }
735 
736  String OntologyUri = "";
737  if(annot.getAnnotType().getUriInOntology() != null){
738  OntologyUri = " ontologyUri=\"" + annot.getAnnotType().getUriInOntology() + "\"";
739  }
740 
741  String typeComment = new String();
742  String tmpComent = "";
743 
744  if(annot.getAnnotType().getComment() != null){
745  tmpComent = annot.getAnnotType().getComment();
746  }
747 
748  if(annot.getAnnotType().getComment() != null)
749  {
750  typeComment = "<comment><![CDATA["
751  + annot.getAnnotType().getComment()
752  + "]]></comment>";
753  }
754 
755  return "<annotation>"
756  + "<rdf:Description rdf:about=\"" + aboutStr + "\">"
757  + "<rdf:type rdf:resource=\"" + annot.getAnnotType().getUri() + OntologyUri + "\">"
758  + "<ancestorsList>"
759  + AnnotationTypeAncestors(annot)
760  + "</ancestorsList>"
761  + typeComment
762  + "</rdf:type>"
763  + "<a:dateTime rdf:value=\"" + Util.toRFC3339Date(annot.getCreated()) + "\" />"
764  + "<a:author id=\"" + annot.getAuthorIdStr() + "\"" + authorAttr + "/>"
765  + "<a:source rdf:resource=\"" + annot.getSource() + "\" uri=\"" + annot.getSourceDocument().getUri() +"\"/>"
766  + fragmentsToXMLStringL(annot,doc)
767  + "<a:content>"
768  + "<![CDATA["
769  + annot.getContent()
770  + "]]>"
771  + "</a:content>"
772  + attributesToXMLStringL(annot,true, false, doc)
773  + "</rdf:Description>"
774  + "</annotation>";
775  } // toXMLString()
776 
777  /**
778  * Returns serialized and linearized informations about annotated fragments in XML
779  *
780  * @param annot annotation which fragments should be serialized
781  * @param doc document tahat fragments belongs
782  * @return Returns serialized informations about annotated fragments in XML
783  */
784  public String fragmentsToXMLStringL(Annotation annot, Document doc) {
785  String LinearizedFragments = "";
786  ArrayList<ArrayList<Fragment>> notConverted = new ArrayList<ArrayList<Fragment>>();
787  ArrayList<ArrayList<Fragment>> comFragments = new ArrayList<ArrayList<Fragment>>();
788  comFragments.add(new ArrayList<Fragment>());
789  Iterator<Fragment> convIt = annot.getFragments().iterator();
790  while(convIt.hasNext()){
791  comFragments.get(0).add(convIt.next());
792  }
793 
794  ArrayList<Fragment> linearizedList;
795  linearizedList = Linearizer.fragmentsToLinFragments(comFragments,doc, notConverted, false);
796 
797  if (notConverted != null) {
798  Iterator<ArrayList<Fragment>> badFrIt = notConverted.iterator();
799  while (badFrIt.hasNext()) {
800  ArrayList<Fragment> badFrListForAnnot = badFrIt.next();
801  Iterator<Fragment> badFrItForAnnot = badFrListForAnnot.iterator();
802  while (badFrItForAnnot.hasNext()) {
803  Fragment fragment = badFrItForAnnot.next();
804  String msg = "This fragment was not linearized successfully: ";
805  msg = msg + " offset: " + fragment.getOffset()
806  + " length: " + fragment.getLength() + " text: " + fragment.getAnnotatedText();
807  Logger.getLogger(StoryscopeInterfaceSender.class.getName()).log(Level.SEVERE, msg);
808  }
809  }
810  }
811 
812  Iterator<Fragment> fragIt = linearizedList.iterator();
813  Fragment fr;
814  while (fragIt.hasNext()) {
815  fr = fragIt.next();
816  if(fr != null)
817  {
818  LinearizedFragments += fr.toXMLString();
819  }
820  }
821  return LinearizedFragments;
822  }
823 
824  /**
825  * Returns serialized informations about annotation attributes in XML
826  *
827  * @param annot Annotation which attributes should be serialized
828  * @param proto11 If true, protocol version is greather then 1.0
829  * @param tmpIdForNested If true, nested annotations will have attribute tmpId
830  * @param doc Annotated document
831  * @return Returns serialized informations about annotation attributes in XML
832  */
833  public String attributesToXMLStringL(Annotation annot, boolean proto11, boolean tmpIdForNested, Document doc) {
834  String attrString = "";
835  Iterator<BaseAttribute> attrIt = annot.getAttributes().iterator();
836  BaseAttribute attr;
837  while (attrIt.hasNext()) {
838  attr = attrIt.next();
839  if(attr instanceof NestedAnnotationAttribute){
840  Annotation nestedAnnot = ((NestedAnnotationAttribute)attr).getNestedAnnotation();
841  if(nestedAnnot != null){
842  attrString += "<a:attribute name=\"" + attr.getName() + "\" type=\"nestedAnnotation\" "
843  + "tmpId=\"" + nestedAnnot.getTmpId() + "\">";
844  attrString += AnnotationToXMLStringL(nestedAnnot,doc);
845 
846  if(attr.getComment() != null){
847  attrString += "<a:comment> <![CDATA[" + attr.getComment() + "]]></a:comment>";
848  }
849  attrString += "</a:attribute>";
850  }
851  }else{
852  attrString += attr.toXMLString(proto11, tmpIdForNested, true);
853  }
854  }
855  return attrString;
856  }
857 } // public class StoryscopeInterfaceSender
ArrayList< Annotation > getRelatedAnnotations(ArrayList< Annotation > approvedAnnot, ArrayList< Annotation > unapprovedAnnot, ArrayList< SubscribedSource > subscribed, ArrayList< SubscribedSource > unsubscribed)
Utility functions for document linearization.
Definition: Linearizer.java:40
Class represent thread of Storyscope Interface that sends messages to StoryScopes.
Class representing annotated copy of document.
Document, annotations and types manipulation functionality.
Class representing StoryScope for needs of SEC Interface.
Definition: StoryScope.java:48
Singleton for storing global variables.
Definition: AppBean.java:47
ArrayList< Annotation > decomposeLinked(ArrayList< Annotation > mainAnnotList, ArrayList< Annotation > secondaryAnnotList, Annotation annot)
static boolean containSourceRule(ArrayList< SubscribedSource > list)
static ArrayList< String > getUserSources(User user)
static String messagesToString(ArrayList< String > messages)
Base class representing attribute of annotation.
Class representing type of annotation.
Definition: AnnotType.java:58
ArrayList< Annotation > getRelatedAnnots(ArrayList< Annotation > approvedAnnot, ArrayList< Annotation > unapprovedAnnot, ArrayList< SubscribedSource > subscribed, ArrayList< SubscribedSource > unsubscribed)
Processed informations about client request.
boolean isSubscribed(Annotation annot, ArrayList< SubscribedSource > unsubscribedSources, ArrayList< SubscribedSource > subscribedSources, ArrayList< String > sources)
String attributesToXMLStringL(Annotation annot, boolean proto11, boolean tmpIdForNested, Document doc)
static boolean containUserRule(ArrayList< SubscribedSource > list)
Informations about client session.
Utility class (manipulates RFC 3339 dates)
Definition: Util.java:29
Class representing annotated fragment.
Definition: Fragment.java:48
int checkBranch(AnnotType rootType, Annotation annot, ArrayList< SubscribedSource > unsubscribedSources, ArrayList< SubscribedSource > subscribedSources, ArrayList< String > sources, ArrayList< SubscribedSource > unsubResult, ArrayList< SubscribedSource > subResult)