4A Server -  2.0
 All Classes Namespaces Files Functions Variables Enumerator
P1Processor.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: P1Processor.java
5  * Description: Class which process XML with messages in 4A protocol v 1.x
6  */
7 
8 /**
9  * @file P1Processor.java
10  *
11  * @brief Class which process XML with messages in 4A protocol v 1.x
12  */
13 
14 /**
15  * @package cz.vutbr.fit.knot.annotations.comet.protocolV1
16  *
17  * @brief Classes which process XML with messages in 4A protocol v 1.x
18  */
19 package cz.vutbr.fit.knot.annotations.comet.protocolV1;
20 
47 
48 import java.security.MessageDigest;
49 import java.security.NoSuchAlgorithmException;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Date;
53 import java.util.HashMap;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.logging.Level;
57 import java.util.logging.Logger;
58 import org.w3c.dom.CharacterData;
59 import org.w3c.dom.DOMException;
60 import org.w3c.dom.Element;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63 
64 /**
65  * Class which process XML with messages in 4A protocol v 1.0 and 1.1
66  *
67  * @brief Class which process XML with messages in 4A protocol v 1.x
68  */
69 public class P1Processor {
70  /**
71  * Processes XML with messages from client
72  *
73  * @param docEl Document element of parsed XML with messages from client
74  * @param requestInfo Informations about client's request
75  * @return Object with informations about client request
76  */
77  public RequestInfo processXML(Element docEl, RequestInfo requestInfo) {
78 
79  EditorSession session = requestInfo.getSession();
80 
81  // ********** login **********
82  User user = null;
83  NodeList loginMsg = docEl.getElementsByTagName("login");
84  Element loginEl = (Element) loginMsg.item(0);
85  if (loginEl != null) { // if login message was sent
86  user = processLogin(loginEl, requestInfo); // process message and returns user or null
87  requestInfo.setLoggedIn(user);
88  session.setUser(user);
89  session.actualizeAllCachedSettings();
90  if (user != null) { // if successfully logged in, prepare logged message
91  AppBean.getSessionsCleaner().setSessionConfirm(session.getSessionId());
92  requestInfo.appendToReply("<logged id=\"" + user.getURI() + "\" name=\"" + user.getName() + "\"/>");
93  }
94  if (user == null) { // if user not logged in, disconnect message still can be processed
95  NodeList disconnMsg = docEl.getElementsByTagName("disconnect");
96  Element disconnEl = (Element) disconnMsg.item(0);
97  if (disconnEl != null) { // if disconnect message was sent
98  if(session.getSyncDocument() != null)
99  {
100  AppBean.decrementDocumentUsage(session.getSyncDocument().getId());
101  }
102  AppBean.removeSession(session); // delete session
103  requestInfo.setDisconnect(true);
104  }
105  return requestInfo;
106  }
107  // Subscribe to own annotations
108  requestInfo.getSession().addSource(new SubscribedSource("*", user.getURI(), null));
109  // subscribe to own groups
111  Iterator<UserGroup> ownGroupsIt = user.getGroups().iterator();
112  while (ownGroupsIt.hasNext()) { // subscribe all own groups
113  UserGroup ownGroup = ownGroupsIt.next();
114  requestInfo.getSession().addSource(new SubscribedSource("*", null, ownGroup.getUri()));
115  }
116  }
117  } // if login message was sent
118 
119  if (user == null) { // if user not set, get him from session
120  user = session.getUser();
121  }
122 
123  if (user == null) { // if user is not set
124  // disconnect message can be processed
125  NodeList disconnMsg = docEl.getElementsByTagName("disconnect");
126  Element disconnEl = (Element) disconnMsg.item(0);
127  int lod = session.getProtocolLOD();
128  requestInfo.addWarning(lod, session.getLanguageNum(), Localisation.WARNING_5_NOT_LOGGED_IN);
130  String msg = "User is not logged in.";
131  Logger.getLogger(MessageProcessor.class.getName()).log(Level.WARNING, msg);
132  }
133  if (disconnEl != null) {
134  //if session have sync. document , it must be decrement in document usage list
135  if(session.getSyncDocument() != null)
136  {
137  AppBean.decrementDocumentUsage(session.getSyncDocument().getId());
138  }
139 
140  AppBean.removeSession(session); // remove session from list of active sessions
141  requestInfo.setDisconnect(true);
142  // Session remains in requestInfo and in flier and after request
143  // is fully processed, it's discarded.
144  }
145  return requestInfo; // no other messages can be processed without logged in user
146  } // if user is not set
147 
148  // ********** queryUserGroups **********
149  NodeList queryUserGroupsMsg = docEl.getElementsByTagName("queryUserGroups");
150  int qGCount = queryUserGroupsMsg.getLength();
151  for (int i = 0; i < qGCount; i++) { // for all messages that was sent
152  Element queryUserGroupsEl = (Element) queryUserGroupsMsg.item(i);
153  Boolean withP = Boolean.parseBoolean(queryUserGroupsEl.getAttribute("withPersons"));
154  String filter = queryUserGroupsEl.getAttribute("filter");
155  if (filter == null || filter.isEmpty()) {
156  filter="*"; // empty filter is equivalent to "*" (all items)
157  }
158  if (withP) { // if groups are queried with persons
159  requestInfo.addQueryUserGroupsWP(filter); // add to appropriate list
160  } else { // if groups are queried without persons
161  requestInfo.addQueryUserGroups(filter);
162  }
163  }
164 
165  // ********** groups (join and leave) **********
166  NodeList joinMsgs = docEl.getElementsByTagName("join");
167  if (joinMsgs.getLength() > 0) { // if message was sent
168  processJoin(joinMsgs, requestInfo);
169  }
170  NodeList leaveMsgs = docEl.getElementsByTagName("leave");
171  if (leaveMsgs.getLength() > 0) { // if message was sent
172  processLeave(leaveMsgs, requestInfo);
173  }
174 
175  if (session.getDefaultGroup() == null) {
176  int lod = requestInfo.getSession().getProtocolLOD();
177  requestInfo.addError(lod, session.getLanguageNum(), Localisation.ERROR_97_NOT_IN_GROUP);
179  String msg = "User is not in any group.";
180  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg);
181  }
182  } else { // if user is in any group
183 
184  // ********** types **********
185  NodeList typesMsg = docEl.getElementsByTagName("types");
186  Element typesEl = (Element) typesMsg.item(0);
187  if (typesEl != null) { // if types message was sent
188  processTypes(typesEl, requestInfo);
189  }
190 
191  // ********** suggestions **********
192  NodeList suggestMsg = docEl.getElementsByTagName("suggestAnnotations");
193  if (suggestMsg.getLength() > 0) { // if messages was sent
194  processSuggestions(suggestMsg, requestInfo); // process messages
195  }
196 
197  // ********** refused suggestions **********
198  NodeList refSuggestMsg = docEl.getElementsByTagName("refusedSuggestions");
199  Element refSuggestEl = (Element) refSuggestMsg.item(0);
200  if (refSuggestEl != null) { // if message was sent
201  processRefSuggestions(refSuggestEl, requestInfo);
202  }
203 
204  } // if user is in any group
205 
206  // ********** settings **********
207  NodeList settingsMsg = docEl.getElementsByTagName("settings");
208  Element settingsEl = (Element) settingsMsg.item(0);
209  if (settingsEl != null) { // if message was sent
210  processSettings(settingsEl, requestInfo);
211  }
212 
213  // ********** entity request **********
214  NodeList entityRequestMsg = docEl.getElementsByTagName("queryEntities");
215  Element entityRequestEl = (Element) entityRequestMsg.item(0);
216  if (entityRequestEl != null) { // if message was sent
217  processEntityRequest(entityRequestEl, requestInfo);
218  }
219 
220  // ********** subscribe **********
221  NodeList subscribeMsg = docEl.getElementsByTagName("subscribe");
222  Element subscribeEl = (Element) subscribeMsg.item(0);
223  if (subscribeEl != null) { // if message was sent
224  processSubscribe(subscribeEl, session, requestInfo);
225  }
226 
227  // ********** unsubscribe **********
228  NodeList unsubscribeMsg = docEl.getElementsByTagName("unsubscribe");
229  Element unsubscribeEl = (Element) unsubscribeMsg.item(0);
230  if (unsubscribeEl != null) { // if message was sent
231  processUnsubscribe(unsubscribeEl, session, requestInfo);
232  }
233 
234  // ********** synchronize **********
235  NodeList synchronizeMsg = docEl.getElementsByTagName("synchronize");
236  Element synchronizeEl = (Element) synchronizeMsg.item(0);
237  if (synchronizeEl != null) { // if message was sent
238  processSynchronize(synchronizeEl, requestInfo);
239  }
240 
241  // ********** resynchronize **********
242  NodeList resynchronizeMsg = docEl.getElementsByTagName("resynchronize");
243  Element resynchronizeEl = (Element) resynchronizeMsg.item(0);
244  if (resynchronizeEl != null) { // if message was sent
245  processResynchronize(resynchronizeEl, requestInfo);
246  }
247 
248  // ********** textModification **********
249  NodeList textModificationMsg = docEl.getElementsByTagName("textModification");
250  if (textModificationMsg.getLength() > 0) { // if messages was sent
251  processTextModificationMsg(textModificationMsg, requestInfo); // process messages
252  }
253 
254  // ********** reload **********
255  NodeList reloadMsg = docEl.getElementsByTagName("reload");
256  if (reloadMsg.getLength() > 0) { // if messages was sent
257  processReload(reloadMsg, requestInfo); // process messages
258  }
259 
260  // ********** queryTypes **********
261  NodeList queryTypesMsg = docEl.getElementsByTagName("queryTypes");
262  Element queryTypesEl = (Element) queryTypesMsg.item(0);
263  if (queryTypesEl != null) { // if message sent
264  String filter = queryTypesEl.getAttribute("filter");
265  if (filter == null || filter.isEmpty()) {
266  filter = "*"; // empty filter is equivalent to "*" (all items)
267  }
268  requestInfo.addQueryTypes(filter);
269  session.addQueriedTypes(filter);
270  }
271 
272  // ********** queryAttrFromOnto **********
273  NodeList queryAttrFromOntoMsg = docEl.getElementsByTagName("queryAttrFromOnto");
274  Element queryAttrFromOntoEl = (Element) queryAttrFromOntoMsg.item(0);
275  if (queryAttrFromOntoEl != null) { // if message sent
276  String attrGr = queryAttrFromOntoEl.getAttribute("group");
277  if (attrGr == null || attrGr.isEmpty()) {
278  attrGr = "*"; // empty group is equivalent to "*" (all items)
279  }
280  requestInfo.setQueryTypeAttOnto(attrGr);
281  }
282 
283  // ********** queryPersons **********
284  NodeList queryPersonsMsg = docEl.getElementsByTagName("queryPersons");
285  int qPCount = queryPersonsMsg.getLength();
286  for (int i= 0; i < qPCount; i++) {
287  Element queryPersonsEl = (Element) queryPersonsMsg.item(i);
288  Boolean withG = Boolean.parseBoolean(queryPersonsEl.getAttribute("withGroups"));
289  String filter = queryPersonsEl.getAttribute("filter");
290  if (filter == null || filter.isEmpty()) {
291  filter = "*"; // empty filter is equivalent to "*" (all items)
292  }
293  if (withG) { // if persons are queried with groups
294  requestInfo.addQueryPersonsWG(filter); // add to appropriate list
295  } else { // if persons are queried without groups
296  requestInfo.addQueryPersons(filter);
297  }
298  }
299 
300  // ********** annotations **********
301  if (session.getDefaultGroup() != null) {
302  NodeList annotationsMsg = docEl.getElementsByTagName("annotations");
303  Element annotationsEl = (Element) annotationsMsg.item(0);
304  if (annotationsEl != null) { // if message sent
305  processAnnotations(annotationsEl, requestInfo);
306  }
307  }
308 
309  // ********** logout **********
310  NodeList logoutMsg = docEl.getElementsByTagName("logout");
311  Element logoutEl = (Element) logoutMsg.item(0);
312  if (logoutEl != null) {
313  if(session.getSyncDocument() != null)
314  {
315  AppBean.decrementDocumentUsage(session.getSyncDocument().getId());
316  }
317  session.setUser(null); // logout user from session
318  requestInfo.setLogout(true);
319  }
320 
321  // ********** disconnect **********
322  NodeList disconnMsg = docEl.getElementsByTagName("disconnect");
323  Element disconnEl = (Element) disconnMsg.item(0);
324  if (disconnEl != null) {
325  if(session.getSyncDocument() != null)
326  {
327  AppBean.decrementDocumentUsage(session.getSyncDocument().getId());
328  }
329  AppBean.removeSession(session); // remove session from list of active sessions
330  requestInfo.setDisconnect(true);
331  // Session remains in requestInfo and in flier and after request
332  // is fully processed, it's discarded.
333  }
334 
335  return requestInfo;
336  } // processXML()
337 
338  /**
339  * Process textModification messages (about modifications of annotated copy of document).
340  * Informations are stored to requestInfo.
341  *
342  * @param tmMsg Messages to process
343  * @param requestInfo Informations about client request
344  */
345  private static void processTextModificationMsg(NodeList tmMsg, RequestInfo requestInfo) {
346  int tmCnt = tmMsg.getLength();
347  for (int i = 0; i < tmCnt; i++) { // for all messages
348  Element tmEl = (Element) tmMsg.item(i);
349  String path = tmEl.getAttribute("path");
350  String offsetString = tmEl.getAttribute("offset");
351  String lengthString = tmEl.getAttribute("length");
352 
353  // parse offset
354  Integer offset = null;
355  if (offsetString != null) {
356  if (!offsetString.isEmpty()) {
357  try {
358  offset = Integer.parseInt(offsetString);
359  } catch (NumberFormatException nfe) { // bad number format - return error message
360  int langNum = requestInfo.getSession().getLanguageNum();
361  int lod = requestInfo.getSession().getProtocolLOD();
362  String info = "<textModification path=\"" + path + "\" offset=\"" + offsetString + "\" length=\"" + lengthString + "\"/>";
363  requestInfo.addError(lod, langNum, Localisation.ERROR_50_BAD_MODIFICATION, info);
365  String msg = "Bad offset in text modification: " + offsetString;
366  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
367  }
368  continue;
369  }
370  }
371  }
372  // parse length
373  Integer length = null;
374  if (lengthString != null) {
375  if (!lengthString.isEmpty()) {
376  try {
377  length = Integer.parseInt(lengthString);
378  } catch (NumberFormatException nfe) { // bad number format - return error message
379  int langNum = requestInfo.getSession().getLanguageNum();
380  int lod = requestInfo.getSession().getProtocolLOD();
381  String info = "<textModification path=\"" + path + "\" offset=\"" + offsetString + "\" length=\"" + lengthString + "\"/>";
382  requestInfo.addError(lod, langNum, Localisation.ERROR_50_BAD_MODIFICATION, info);
384  String msg = "Bad length in text modification: " + lengthString;
385  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
386  }
387  continue;
388  }
389  }
390  }
391  // get new content
392  String newContent = MessageProcessor.getElementContent(tmEl);
393  /*if (newContent == null) { // content can be empty, but can't be null
394  int langNum = requestInfo.getSession().getLanguageNum();
395  String info = "<textModification path=\"" + path + "\" offset=\"" + offsetString + "\" length=\"" + lengthString + "\"/>";
396  requestInfo.addError(langNum, Localisation.ERROR_50_BAD_MODIFICATION, info);
397  if (Constants.LOG_LEVEL >= Constants.LOG_LEVEL_ALL_ERRORS) {
398  String msg = "NULL content in text modification.";
399  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
400  }
401  continue;
402  }*/
403  // improve XPath to be usable
404  path = UpdatableFragment.improveXPath(path);
405  // create object wit informations and add to flier
406  TextModification newMod = new TextModification(path, offset, length, newContent);
407  requestInfo.addTextModification(newMod);
408  } // for all messages
409  } // processTextModificationMsg()
410 
411  /**
412  * Process reload messages (about query to annotations).
413  * Informations are stored to requestInfo.
414  *
415  * @param reloadMsg Messages to process
416  * @param requestInfo Informations about client request
417  */
418  private static void processReload(NodeList reloadMsg, RequestInfo requestInfo) {
419  int reloadCnt = reloadMsg.getLength();
420  for (int i = 0; i < reloadCnt; i++) { // for all reload messages
421  Element reloadEl = (Element) reloadMsg.item(i);
422  String all = reloadEl.getAttribute("all");
423  boolean reloadAllAnnots = false;
424 
425  if (all != null && all.equalsIgnoreCase("true")) {
426  requestInfo.setReloadAll(true);
427  reloadAllAnnots = true;
428  }
429  String reloadedUri = reloadEl.getAttribute("uri");
430  if (reloadedUri == null) {
431  reloadedUri = "";
432  }
433  // get id of annotation by strip off base URI
434  String reloadIdStr = reloadedUri.replace(AppBean.getBaseAnnotUri(), "");
435  // parse id of annotation
436  Integer reloadId = null;
437  if (!reloadIdStr.isEmpty()) {
438  try {
439  reloadId = Integer.parseInt(reloadIdStr);
440  } catch (NumberFormatException nfe) {
442  String msg = "Bad id of reloaded annotation: " + reloadIdStr;
443  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
444  }
445  reloadId = null;
446  }
447  }
448  if (reloadId != null) { // if id of annotation is available
449  // query database for annotation
450  Object[] params = new Object[2];
451  params[0] = "id";
452  params[1] = reloadId;
453  List rList = AppBean.getPersistenceManager().queryDB("Annotation.findById", params);
454  if (rList != null && !rList.isEmpty()) { // if annotation was found
455  Annotation relAnnot = (Annotation) rList.get(0);
456  requestInfo.addReloadAnnotations(relAnnot); // add to list
457  } else { // if annotation wasn't found - error
458  int langNum = requestInfo.getSession().getLanguageNum();
459  int lod = requestInfo.getSession().getProtocolLOD();
460  String info = "<reload uri=\"" + reloadedUri + "\"/>";
461  requestInfo.addError(lod, langNum, Localisation.ERROR_34_RELOAD_ANNOT_NOT_FOUND, info);
463  String msg = "Reloaded annotation was not found: " + reloadId;
464  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
465  }
466  }
467  } else { // if id isn't presented or it's malformed
468  if(!reloadAllAnnots){
469  int langNum = requestInfo.getSession().getLanguageNum();
470  int lod = requestInfo.getSession().getProtocolLOD();
471  String info = "<reload uri=\"" + reloadedUri + "\"/>";
472  requestInfo.addError(lod, langNum, Localisation.ERROR_34_RELOAD_ANNOT_NOT_FOUND, info);
474  String msg = "Id of reloaded annotation missing.";
475  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
476  }
477  }
478  }
479  } // for all reload messages
480  } // processReload()
481 
482  /**
483  * Process join messages (join to user group)
484  * Informations are stored into requestInfo and user is added into group
485  * (no additional operations needed).
486  *
487  * @param joinMsgs Messages to process
488  * @param requestInfo Informations about client request
489  */
490  private static void processJoin(NodeList joinMsgs, RequestInfo requestInfo) {
491  int joinCnt = joinMsgs.getLength();
492  User user = requestInfo.getSession().getUser();
493  for (int i = 0; i < joinCnt; i++) { // for all join messages
494  Element joinEl = (Element) joinMsgs.item(i);
495  String groupUri = joinEl.getAttribute("group");
496  if (groupUri == null) {
497  groupUri = "";
498  }
499  // get id of user group by strip off base URI
500  String groupIdStr = groupUri.replace(AppBean.getBaseGroupUri(), "");
501  // parse id of user group
502  Integer groupId = null;
503  if (!groupIdStr.isEmpty()) {
504  try {
505  groupId = Integer.parseInt(groupIdStr);
506  } catch (NumberFormatException nfe) {
508  String msg = "Bad id of joined group: " + groupIdStr;
509  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
510  }
511  groupId = null;
512  }
513  }
514  if (groupId != null) { // if id of group is available
515  // query database for group
516  Object[] params = new Object[2];
517  params[0] = "id";
518  params[1] = groupId;
519  List gList = AppBean.getPersistenceManager().queryDB("UserGroup.findById", params);
520  if (gList != null && !gList.isEmpty()) { // if group was found
521  UserGroup jGroup = (UserGroup) gList.get(0);
522  if (!user.getGroups().contains(jGroup)) { // if user isn't in this group
523  if (jGroup.getName().equalsIgnoreCase(Constants.ADMIN_GROUP)) {
524  int langNum = requestInfo.getSession().getLanguageNum();
525  int lod = requestInfo.getSession().getProtocolLOD();
526  String info = "<group uri=\"" + groupUri + "\"/>";
527  requestInfo.addError(lod, langNum, Localisation.ERROR_57_JOIN_ADMINISTRATORS, info);
529  String msg = "User is trying to join to administrators: " + user.getName();
530  Logger.getLogger(MessageProcessor.class.getName()).log(Level.WARNING, msg);
531  }
532  } else {
533  user.addGroup(jGroup); // add group to user's groups
534  jGroup.addUser(user); // add user to group
535  requestInfo.addJoinedGroup(jGroup); // add group into list of just added groups
536  }
537  }
538  } else { // if group wasn't found - error
539  int langNum = requestInfo.getSession().getLanguageNum();
540  int lod = requestInfo.getSession().getProtocolLOD();
541  String info = "<group uri=\"" + groupUri + "\"/>";
542  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
544  String msg = "Group to join was not found.";
545  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
546  }
547  }
548  } else { // if id of group isn't presented or it's malformed
549  int langNum = requestInfo.getSession().getLanguageNum();
550  int lod = requestInfo.getSession().getProtocolLOD();
551  String info = "<group uri=\"" + groupUri + "\"/>";
552  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
554  String msg = "Join to group without group id.";
555  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
556  }
557  }
558  } // for all join messages
559  } // processJoin()
560 
561  /**
562  * Process leave messages (leave user group)
563  * Informations are stored into requestInfo and user is femoved from group
564  * (no additional operations needed).
565  *
566  * @param leaveMsgs Messages to process
567  * @param requestInfo Informations about client request
568  */
569  private static void processLeave(NodeList leaveMsgs, RequestInfo requestInfo) {
570  int leaveCnt = leaveMsgs.getLength();
571  User user = requestInfo.getSession().getUser();
572  for (int i = 0; i < leaveCnt; i++) { // for all leave messages
573  Element leaveEl = (Element) leaveMsgs.item(i);
574  String groupUri = leaveEl.getAttribute("group");
575  if (groupUri == null) {
576  groupUri = "";
577  }
578  // get id of user group by strip off base URI
579  String groupIdStr = groupUri.replace(AppBean.getBaseGroupUri(), "");
580  // parse id of user group
581  Integer groupId = null;
582  if (!groupIdStr.isEmpty()) {
583  try {
584  groupId = Integer.parseInt(groupIdStr);
585  } catch (NumberFormatException nfe) {
586  groupId = null;
588  String msg = "Bad id of leaved group: " + groupIdStr;
589  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
590  }
591  }
592  }
593  if (groupId != null) { // if id of group is available
594  // query database for group
595  Object[] params = new Object[2];
596  params[0] = "id";
597  params[1] = groupId;
598  List gList = AppBean.getPersistenceManager().queryDB("UserGroup.findById", params);
599  if (gList != null && !gList.isEmpty()) {
600  UserGroup lGroup = (UserGroup) gList.get(0);
601  if (user.getGroups().contains(lGroup)) { // if user is in this group
602  if (lGroup.getName().equalsIgnoreCase(Constants.ADMIN_GROUP) && lGroup.getUsers().size() < 2) {
603  int langNum = requestInfo.getSession().getLanguageNum();
604  int lod = requestInfo.getSession().getProtocolLOD();
605  String info = "<group uri=\"" + groupUri + "\"/>";
606  requestInfo.addError(lod, langNum, Localisation.ERROR_58_LAST_ADMIN, info);
608  String msg = "Last administrator is trying to leave group.";
609  Logger.getLogger(MessageProcessor.class.getName()).log(Level.WARNING, msg);
610  }
611  } else {
612  user.getGroups().remove(lGroup); // remove group from user's groups
613  lGroup.getUsers().remove(user); // remove user from group
614  requestInfo.addLeavedGroup(lGroup); // add group to list of just leaved groups
615  }
616  } else { // if user isn't in this group
617  int langNum = requestInfo.getSession().getLanguageNum();
618  int lod = requestInfo.getSession().getProtocolLOD();
619  String info = "<group uri=\"" + groupUri + "\"/>";
620  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
622  String msg = "Group to leave is not in joined groups.";
623  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
624  }
625  }
626  } else { // if group wasn't found - error
627  int langNum = requestInfo.getSession().getLanguageNum();
628  int lod = requestInfo.getSession().getProtocolLOD();
629  String info = "<group uri=\"" + groupUri + "\"/>";
630  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
632  String msg = "Group to leave was not found.";
633  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
634  }
635  }
636  } else { // if id of group isn't presented or it's malformed
637  int langNum = requestInfo.getSession().getLanguageNum();
638  int lod = requestInfo.getSession().getProtocolLOD();
639  String info = "<group uri=\"" + groupUri + "\"/>";
640  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
642  String msg = "Leave without group id.";
643  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
644  }
645  }
646  } // for all leave messages
647  } // processLeave()
648 
649  /**
650  * Process annotations message (added, changed and removed annotations)
651  * Informations are stored into requestInfo.
652  *
653  * @param annotationsEl Element with message to process
654  * @param requestInfo Informations about client request
655  */
656  private static void processAnnotations(Element annotationsEl, RequestInfo requestInfo) {
657  Flier flier = requestInfo.getFlier();
658  if (requestInfo.getSession().getSyncDocument() == null) { // if not synchronized
659  // annotations can't be processed
660  int langNum = requestInfo.getSession().getLanguageNum();
661  int lod = requestInfo.getSession().getProtocolLOD();
662  requestInfo.addError(lod, langNum, Localisation.ERROR_43_NOT_SYNCHRONIZED);
664  String msg = "Not synchronized and trying to create annotations.";
665  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
666  }
667  return;
668  }
669  // get element with added annotations
670  NodeList addedNL = annotationsEl.getElementsByTagName("add");
671  if (addedNL.getLength() == 0) { // if it's not presented, try older version
672  addedNL = annotationsEl.getElementsByTagName("added");
673  }
674  Element addEl = (Element) addedNL.item(0);
675  if (addEl != null) { // if element with added annotations is presented
676  // get elements with annotations
677  NodeList addAnnotNodes = addEl.getElementsByTagName("annotation");
678  int addedAnnotCnt = addAnnotNodes.getLength();
679  for (int i = 0; i < addedAnnotCnt; i++) { // for all annotation elements
680  Element addedAnnotEl = (Element) addAnnotNodes.item(i);
681  if (addedAnnotEl.getParentNode() != addEl) {
682  // if it's nested annotation at any level
683  continue; // skip
684  }
685  // process element
686  Annotation addedAnnot = processAddedAnnotEl(addedAnnotEl, requestInfo);
687  if (addedAnnot != null) { // if element was successfully processed
688  flier.AddAddedAnnotation(addedAnnot); // add annotation to flier
689  }
690  }
691  }
692  // get element with changed annotations
693  NodeList editedNL = annotationsEl.getElementsByTagName("change");
694  if (editedNL.getLength() == 0) { // if it's not presented, try older version
695  editedNL = annotationsEl.getElementsByTagName("edited");
696  }
697  Element editedEl = (Element) editedNL.item(0);
698  if (editedEl != null) { // if element with changed annotations is presented
699  // get elements with annotations
700  NodeList updateAnnotNodes = editedEl.getElementsByTagName("annotation");
701  int updatedAnnotCnt = updateAnnotNodes.getLength();
702  for (int i = 0; i < updatedAnnotCnt; i++) { // for all annotation elements
703  Element updatedAnnotEl = (Element) updateAnnotNodes.item(i);
704  if (updatedAnnotEl.getParentNode() != editedEl) {
705  // if it's nested annotation at any level
706  continue; // skip
707  }
708  // process element
709  Annotation editedAnnot = processEditedAnnotEl(updatedAnnotEl, requestInfo);
710  if (editedAnnot != null) { // if element was successfully processed
711  flier.AddEditedAnnotation(editedAnnot); // add annotation to flier
712  }
713  }
714  }
715  // get element with removed annotations
716  NodeList removedNL = annotationsEl.getElementsByTagName("remove");
717  if (removedNL.getLength() == 0) { // if it's not presented, try older version
718  removedNL = annotationsEl.getElementsByTagName("removed");
719  }
720  Element removedEl = (Element) removedNL.item(0);
721  if (removedEl != null) {
722  // get elements with annotations
723  NodeList remAnnotNodes = removedEl.getElementsByTagName("annotation");
724  int remAnnotCnt = remAnnotNodes.getLength();
725  for (int i = 0; i < remAnnotCnt; i++) { // for all annotation elements
726  Element remAnnotEl = (Element) remAnnotNodes.item(i);
727  if (remAnnotEl.getParentNode() != removedEl) {
728  // if it's nested annotation at any level
729  continue; // skip
730  }
731  // process element
732  Annotation removedAnnot = processRemAnnotEl(remAnnotEl, requestInfo);
733  if (removedAnnot != null) { // if element was successfully processed
734  flier.AddRemovedAnnotation(removedAnnot); // add annotation to flier
735  }
736  }
737  } // if (removedEl != null) ...
738  } // processAnnotations()
739 
740  /**
741  * Process element with added annotation.
742  * If error occurs, generates error message.
743  *
744  * @param addedAnnotEl Element with added annotation to process
745  * @param requestInfo Informations about client request
746  * @return If element was successfully processed, returns annotation, if error occurred, returns null
747  */
748  private static Annotation processAddedAnnotEl(Element addedAnnotEl, RequestInfo requestInfo) {
749  Annotation retAnnot = null;
750  // get attributes of annotation element (informations about suggestions)
751  String confirmed = addedAnnotEl.getAttribute("confirmed");
752  String tmpId = addedAnnotEl.getAttribute("tmpId");
753  if (tmpId == null) {
754  tmpId = "";
755  }
756  // get element with annotation data
757  NodeList annotDescNL = addedAnnotEl.getElementsByTagName("rdf:Description");
758  int nCount = annotDescNL.getLength();
759  int ni = 0;
760  Element annotDescEl = (Element) annotDescNL.item(ni);
761  if (tmpId.isEmpty()) {
762  tmpId = annotDescEl.getAttribute("tmpId");
763  if (tmpId == null) {
764  tmpId = "";
765  }
766  }
767  ni++;
768  if (annotDescEl == null) {
769  int langNum = requestInfo.getSession().getLanguageNum();
770  int lod = requestInfo.getSession().getProtocolLOD();
771  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
773  String msg = "Annotation description element is missing.";
774  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
775  }
776  return null; // no annotation returned
777  }
778  while (annotDescEl.getParentNode() != addedAnnotEl && ni < nCount) {
779  // find proper element
780  annotDescEl = (Element) annotDescNL.item(ni);
781  ni++;
782  }
783  if (annotDescEl.getParentNode() != addedAnnotEl) { // check element
784  // if element is not on the proper level
785  int langNum = requestInfo.getSession().getLanguageNum();
786  int lod = requestInfo.getSession().getProtocolLOD();
787  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
789  String msg = "Annotation description element is missing.";
790  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
791  }
792  return null; // no annotation returned
793  }
794  Integer cMethod = Constants.CONFIRM_METHODS.indexOf(confirmed);
795  if (cMethod < 0) { // unknown method
796  cMethod = null;
797  }
798  // process element with annotation data
799  retAnnot = processAnnotationDescEl(annotDescEl, requestInfo, null, cMethod);
800  if (retAnnot == null) { // if error occurred
802  String msg = "Bad annotation description: " + annotDescEl.toString();
803  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
804  }
805  return null; // no annotation returned
806  }
807  if (retAnnot.getAuthorIdStr() == null) { // if author's URI wasn't set
808  // set informations about annotation author
809  User user = requestInfo.getSession().getUser();
810  retAnnot.setAuthorIdStr(AppBean.getBaseAuthorUri() + user.getId());
811  retAnnot.setAuthorName(user.getName());
812  retAnnot.setAuthorAddress(user.getEmail());
813  }
814  if (!tmpId.isEmpty()) { // if this annotation is confirmed suggestion
815  // parse confirmation method
816  Integer method = Constants.CONFIRM_METHODS.indexOf(confirmed);
817  if (method < 0) { // unknown method
818  int langNum = requestInfo.getSession().getLanguageNum();
819  int lod = requestInfo.getSession().getProtocolLOD();
820  requestInfo.addError(lod, langNum, Localisation.ERROR_28_BAD_CONFIRM);
822  String msg = "Bad confirmation method: ";
823  if (confirmed != null) {
824  msg = msg + confirmed;
825  }
826  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
827  }
828  method = Constants.CONFIRMED_AUTOMATICALLY; // set to automatically (low confidence)
829  }
830  if (tmpId != null) { // if id of suggestion is available
831  EditorSession session = requestInfo.getSession();
832  // find suggestion
833  SuggestionLogEntry cmp = new SuggestionLogEntry(tmpId);
834 
835  if (requestInfo.getSession().getSendedSuggestions() != null && !requestInfo.getSession().getSendedSuggestions().isEmpty()) {
836  Integer id = null;
837  try {
838  id = Integer.parseInt(tmpId);
839  } catch (NumberFormatException nfe) {
841  String msg = "The ID of the confirmed suggestion is not a number: " + tmpId;
842  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
843  }
844  }
845  // ID was parsed successfuly and the ID is contained within sended suggestions
846  if (id != null && requestInfo.getSession().isSuggInSendedSuggestions(id)) {
847  SuggestionLogEntry newEntry = new SuggestionLogEntry(tmpId);
848  // set informations about confirmation
849  retAnnot.setTmpId(tmpId);
850  retAnnot.setId(null);
851  newEntry.setConfirmMethod(method);
852  newEntry.setConfirmedVersion(retAnnot);
853  // add to list of confirmed suggestions
854  if (!requestInfo.getConfirmedSuggestions().contains(newEntry)) {
855  requestInfo.addConfirmedSuggestion(newEntry);
856  }
857  } else { // the suggestion's not been found
859  String msg = "Suggestion with the following ID not found: " + tmpId;
860  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
861  }
862  }
863  }
864  }
865  } // if this annotation is confirmed suggestion
866  return retAnnot;
867  } // processAddedAnnotEl()
868 
869  /**
870  * Process element with changed annotation.
871  * If error occurs, generates error message.
872  *
873  * @param updatedAnnotEl Element with changed annotation to process
874  * @param requestInfo Informations about client request
875  * @return If element was successfully processed, returns annotation, if error occurred, returns null
876  */
877  private static Annotation processEditedAnnotEl(Element updatedAnnotEl, RequestInfo requestInfo) {
878  Annotation retAnnot = null;
879  // get element with annotation data
880  NodeList annotDescNL = updatedAnnotEl.getElementsByTagName("rdf:Description");
881  int nCount = annotDescNL.getLength();
882  int ni = 0;
883  Element annotDescEl = (Element) annotDescNL.item(ni);
884  ni++;
885  if (annotDescEl == null) {
886  int langNum = requestInfo.getSession().getLanguageNum();
887  int lod = requestInfo.getSession().getProtocolLOD();
888  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
890  String msg = "Annotation description element of edited annotation is missing.";
891  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
892  }
893  return null; // no annotation returned
894  }
895  while (annotDescEl.getParentNode() != updatedAnnotEl && ni < nCount) {
896  // find proper element
897  annotDescEl = (Element) annotDescNL.item(ni);
898  ni++;
899  }
900  if (annotDescEl.getParentNode() != updatedAnnotEl) { // check element
901  // if element is not on the proper level
902  int langNum = requestInfo.getSession().getLanguageNum();
903  int lod = requestInfo.getSession().getProtocolLOD();
904  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
906  String msg = "Annotation description element of edited annotation is missing.";
907  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
908  }
909  return null; // no annotation returned
910  }
911  // get URI of annotation
912  String annotUri = annotDescEl.getAttribute("rdf:about");
913  // get id of annotation (strip off base URI)
914  String annotIdStr = annotUri.replace(AppBean.getBaseAnnotUri(), "");
915  // parse id of annotation
916  Integer annotId = null;
917  try {
918  annotId = Integer.parseInt(annotIdStr);
919  } catch (NumberFormatException nfe) { // malformed id - error
920  int langNum = requestInfo.getSession().getLanguageNum();
921  int lod = requestInfo.getSession().getProtocolLOD();
922  String info = "<reload uri=\"" + annotUri + "\"/>";
923  requestInfo.addError(lod, langNum, Localisation.ERROR_29_CHANGED_ANNOT_NOT_FOUND, info);
925  String msg = "Bad id of edited annotation: " + annotIdStr;
926  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
927  }
928  return null;
929  }
930 
931  // query database for annotation
932  Object[] params = new Object[2];
933  params[0] = "id";
934  params[1] = annotId;
935  List aList = AppBean.getPersistenceManager().queryDB("Annotation.findById", params);
936  if (aList != null && !aList.isEmpty()) { // if annotation was found
937  retAnnot = (Annotation) aList.get(0);
938  } else { // if annotation wasn't found - error
939  int langNum = requestInfo.getSession().getLanguageNum();
940  int lod = requestInfo.getSession().getProtocolLOD();
941  String info = "<reload uri=\"" + annotUri + "\"/>";
942  requestInfo.addError(lod, langNum, Localisation.ERROR_29_CHANGED_ANNOT_NOT_FOUND, info);
944  String msg = "Edited annotation was not found.";
945  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
946  }
947  return null; // unknown annotation can't be changed
948  }
949 
950  // process element with annotation data
951  Annotation annotFromEl = processAnnotationDescEl(annotDescEl, requestInfo, null, null);
952  if (annotFromEl != null) { // if element was successfully processed
953  annotFromEl.setId(retAnnot.getId()); // set id of annotation to id of its old version
954  } else { // if error occurred
956  String msg = "Bad edited annotation description: " + annotDescEl.toString();
957  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
958  }
959  return null;
960  }
961  return annotFromEl;
962  } // processEditedAnnotEl()
963 
964  /**
965  * Process element with removed annotation.
966  * If error occurs, generates error message.
967  *
968  * @param remAnnotEl Element with removed annotation to process
969  * @param requestInfo Informations about client request
970  * @return If element was successfully processed, returns annotation, if error occurred, returns null
971  */
972  private static Annotation processRemAnnotEl(Element remAnnotEl, RequestInfo requestInfo) {
973  Annotation retAnnot = null;
974  // get element with annotation data
975  NodeList annotDescNL = remAnnotEl.getElementsByTagName("rdf:Description");
976  int nCount = annotDescNL.getLength();
977  int ni = 0;
978  Element annotDescEl = (Element) annotDescNL.item(ni);
979  ni++;
980  if (annotDescEl == null) {
981  int langNum = requestInfo.getSession().getLanguageNum();
982  int lod = requestInfo.getSession().getProtocolLOD();
983  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
985  String msg = "Annotation description element of removed annotation is missing.";
986  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
987  }
988  return null; // no annotation returned
989  }
990  while (annotDescEl.getParentNode() != remAnnotEl && ni < nCount) {
991  // find proper element
992  annotDescEl = (Element) annotDescNL.item(ni);
993  ni++;
994  }
995  if (annotDescEl.getParentNode() != remAnnotEl) { // check element
996  int langNum = requestInfo.getSession().getLanguageNum();
997  int lod = requestInfo.getSession().getProtocolLOD();
998  requestInfo.addError(lod, langNum, Localisation.ERROR_54_BAD_ANNOT_DESCRIPTION);
1000  String msg = "Annotation description element of removed annotation is missing.";
1001  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1002  }
1003  return null; // no annotation returned
1004  }
1005  // get URI of annotation
1006  String annotUri = annotDescEl.getAttribute("rdf:about");
1007  // get id of annotation (strip off base URI)
1008  String annotIdStr = annotUri.replace(AppBean.getBaseAnnotUri(), "");
1009  // parse id of annotation
1010  Integer annotId = null;
1011  try {
1012  annotId = Integer.parseInt(annotIdStr);
1013  } catch (NumberFormatException nfe) { // malformed id - error
1014  String info = "<reload uri=\"" + annotUri + "\"/>";
1015  int langNum = requestInfo.getSession().getLanguageNum();
1016  int lod = requestInfo.getSession().getProtocolLOD();
1017  requestInfo.addError(lod, langNum, Localisation.ERROR_30_REM_ANNOT_NOT_FOUND, info);
1019  String msg = "Bad id of removed annotation: " + annotIdStr;
1020  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1021  }
1022  return null;
1023  }
1024 
1025  // query database for annotation
1026  Object[] params = new Object[2];
1027  params[0] = "id";
1028  params[1] = annotId;
1029  List aList = AppBean.getPersistenceManager().queryDB("Annotation.findById", params);
1030  if (aList != null && !aList.isEmpty()) { // if annotation was found
1031  retAnnot = (Annotation) aList.get(0);
1032  } else { // if annotation wasn't found
1033  int langNum = requestInfo.getSession().getLanguageNum();
1034  int lod = requestInfo.getSession().getProtocolLOD();
1035  String info = "<reload uri=\"" + annotUri + "\"/>";
1036  requestInfo.addError(lod, langNum, Localisation.ERROR_30_REM_ANNOT_NOT_FOUND, info);
1038  String msg = "Removed annotation was not found.";
1039  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1040  }
1041  return null; // unknown annotation can't be removed
1042  }
1043  return retAnnot;
1044  } // processRemAnnotEl()
1045 
1046  /**
1047  * Process element with annotation data.
1048  * If error occurs, generates error message.
1049  * For nested annotations it's called recursively.
1050  *
1051  * @param annotationEl Element with annotation data to process
1052  * @param requestInfo Informations about client request
1053  * @param nestedIn If this annotation is nested, then parent annotation, null otherwise
1054  * @param cMethod Confirmation method of parent annotation or null
1055  * @return If element was successfully processed, returns annotation, if error occurred, returns null
1056  */
1057  private static Annotation processAnnotationDescEl(Element annotationEl, RequestInfo requestInfo, Annotation nestedIn, Integer cMethod) {
1058  EditorSession session = requestInfo.getSession();
1059  Flier flier = requestInfo.getFlier();
1060  Annotation retAnnot = null;
1061  // get URI of annotation
1062  String annotUri = annotationEl.getAttribute("rdf:about");
1063  if (annotUri == null) {
1064  annotUri = "";
1065  }
1066  String tmpId = annotationEl.getAttribute("tmpId");
1067  // prepare informations for error message
1068  String errInfo = "";
1069  if (!annotUri.isEmpty()) {
1070  errInfo = "<reload uri=\"" + annotUri + "\"/>";
1071  }
1072 
1073  // get element with annotation type
1074  NodeList typeNL = annotationEl.getElementsByTagName("rdf:type");
1075  Element typeEl = (Element) typeNL.item(0);
1076  if (typeEl == null) {
1077  int langNum = session.getLanguageNum();
1078  int lod = requestInfo.getSession().getProtocolLOD();
1079  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, errInfo);
1081  String msg = "Annotation type element is missing.";
1082  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1083  }
1084  return null;
1085  }
1086  // get URI of annotation type
1087  String annotTypeStr = typeEl.getAttribute("rdf:resource");
1088  // query database for annotation type
1089  AnnotType annotType = null;
1090  Object[] params = new Object[2];
1091  params[0] = "uri";
1092  params[1] = annotTypeStr;
1093  List aList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
1094  if (aList != null && !aList.isEmpty()) { // if type was found
1095  annotType = (AnnotType) aList.get(0);
1096  } else { // type was not found, it possibly can be new type
1097  Iterator<AnnotType> atIter = (Iterator<AnnotType>) flier.getAddedTypes().iterator();
1098  while (atIter.hasNext() && annotType == null) { // look over just added types
1099  AnnotType addedT = atIter.next();
1100  if (addedT.getUri().equals(annotTypeStr)) { // if type was found
1101  annotType = addedT;
1102  }
1103  }
1104  }
1105  if (annotType == null && annotTypeStr.contains(AppBean.getBaseTypeUri())) {
1106  // possible client with bad protocol (he don't supply group id)
1107 
1108  // assemble base URI with default user group for this user
1109  String baseWG = AppBean.getBaseTypeUri() + "g" + requestInfo.getSession().getDefaultGroup().getId() + "/";
1110  // replace base URI with new URI
1111  String pomTypeStr = annotTypeStr.replace(AppBean.getBaseTypeUri(), baseWG);
1112  // query database for annotation type with corrected URI
1113  params[1] = pomTypeStr;
1114  aList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
1115  if (aList != null && !aList.isEmpty()) { // if type was found
1116  annotType = (AnnotType) aList.get(0);
1117  } else { // type was not found, it possibly can be new type
1118  Iterator<AnnotType> atIter = (Iterator<AnnotType>) flier.getAddedTypes().iterator();
1119  while (atIter.hasNext() && annotType == null) { // look over just added types
1120  AnnotType addedT = atIter.next();
1121  if (addedT.getUri().equals(pomTypeStr)) { // if type was found
1122  annotType = addedT;
1123  }
1124  }
1125  }
1126  }
1127  if (annotType == null) { // if annotation type was not found - error
1128  int langNum = requestInfo.getSession().getLanguageNum();
1129  int lod = requestInfo.getSession().getProtocolLOD();
1130  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, errInfo);
1132  String msg = "Annotation type not found: " + annotTypeStr;
1133  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1134  }
1135  return null;
1136  }
1137 
1138  // get element with date of creation
1139  NodeList dateNL = annotationEl.getElementsByTagName("a:dateTime");
1140  Element dateEl = (Element) dateNL.item(0);
1141  Date annotDate = null;
1142  if (dateEl == null) { // if date is missing
1143  annotDate = new Date(); // use actual date
1144  } else { // if date is set
1145  // get date of creation
1146  String dateString = dateEl.getAttribute("rdf:value");
1147  // parse date of creation
1148  try {
1149  annotDate = Util.parseRFC3339Date(dateString);
1150  } catch (Exception e) { // malformed date - error
1151  int langNum = requestInfo.getSession().getLanguageNum();
1152  int lod = requestInfo.getSession().getProtocolLOD();
1153  requestInfo.addError(lod, langNum, Localisation.ERROR_41_BAD_DATE_FORMAT_ANNOT, errInfo);
1155  String msg = "Bad date of annotation creation: " + dateString;
1156  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1157  }
1158  annotDate = new Date(); // replace with actual date
1159  }
1160  }
1161 
1162  // get element with annotation author
1163  NodeList authorNL = annotationEl.getElementsByTagName("a:author");
1164  Element authorEl = (Element) authorNL.item(0);
1165  if (authorEl == null) {
1166  int langNum = requestInfo.getSession().getLanguageNum();
1167  int lod = requestInfo.getSession().getProtocolLOD();
1168  requestInfo.addError(lod, langNum, Localisation.ERROR_44_ANNOT_AUTHOR, errInfo);
1169  return null; // annotation cannot be processed
1170  }
1171  // get informations about author
1172  String authorName = authorEl.getAttribute("name"); // full name
1173  String authorAddress = authorEl.getAttribute("address"); // email
1174  String authorIdStr = authorEl.getAttribute("id"); // URI
1175  if (authorIdStr == null) {
1176  authorIdStr = "";
1177  } else { // if URI of author was set, strip off base URI and get id of author
1178  authorIdStr = authorIdStr.replace(AppBean.getBaseAuthorUri(), "");
1179  }
1180  // parse id of author
1181  Integer authorId = null;
1182  if (!authorIdStr.isEmpty()) {
1183  try {
1184  authorId = Integer.parseInt(authorIdStr);
1185  } catch (NumberFormatException nfe) { // malformed id - error
1186  int langNum = requestInfo.getSession().getLanguageNum();
1187  int lod = requestInfo.getSession().getProtocolLOD();
1188  requestInfo.addError(lod, langNum, Localisation.ERROR_44_ANNOT_AUTHOR, errInfo);
1190  String msg = "Bad id of annotation author: " + authorIdStr;
1191  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1192  }
1193  return null; // annotation cannot be processed
1194  }
1195  }
1196 
1197  // get element with URI of annotated copy of document
1198  NodeList sourceNL = annotationEl.getElementsByTagName("a:source");
1199  Element sourceEl = (Element) sourceNL.item(0);
1200  if (sourceEl == null) {
1201  int langNum = requestInfo.getSession().getLanguageNum();
1202  int lod = requestInfo.getSession().getProtocolLOD();
1203  requestInfo.addError(lod, langNum, Localisation.ERROR_24_BAD_SOURCE_IN_ANNOT, errInfo);
1205  String msg = "Source element is missing in annotation.";
1206  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1207  }
1208  return null;
1209  }
1210  // get URI of annotated copy of document
1211  String annotSource = sourceEl.getAttribute("rdf:resource");
1212  if (annotSource == null) {
1213  annotSource = "";
1214  }
1215  if (annotSource.isEmpty()) { // if URI is empty, use URI of synchronized document
1216  annotSource = session.getSyncDocument().getUri();
1217  } else if (!annotSource.equals(session.getSyncDocument().getUriForAnnot())) {
1218  // if it's not URI of synchronized document - error
1219  int langNum = requestInfo.getSession().getLanguageNum();
1220  int lod = requestInfo.getSession().getProtocolLOD();
1221  requestInfo.addError(lod, langNum, Localisation.ERROR_24_BAD_SOURCE_IN_ANNOT, errInfo);
1223  String msg = "Source in annotation is not matching to synchronized document.";
1224  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1225  }
1226  return null;
1227  }
1228 
1229  // get textual content of annotation
1230  NodeList contentNL = annotationEl.getElementsByTagName("a:content");
1231  Element contentEl = (Element) contentNL.item(0);
1232  String content = MessageProcessor.getElementContent(contentEl);
1233  if (content == null) {
1234  content = "";
1235  }
1236 
1237  // create annotation object
1238  retAnnot = new Annotation(annotType, annotDate, authorIdStr, authorName, authorAddress, session.getSyncDocument(), content, nestedIn);
1239 
1240  retAnnot.setTmpId(tmpId);
1241  SuggestionLogEntry newEntry = null;
1242  if (nestedIn != null) {
1243  if (requestInfo.getSession().getSendedSuggestions() != null && !requestInfo.getSession().getSendedSuggestions().isEmpty()) {
1244  Integer id = null;
1245  try {
1246  id = Integer.parseInt(tmpId);
1247  } catch (NumberFormatException nfe) {
1249  String msg = "The ID of the refused suggestion is not a number: " + tmpId;
1250  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1251  }
1252  }
1253  int method = Constants.CONFIRMED_AUTOMATICALLY;
1254  if (cMethod != null) {
1255  method = cMethod;
1256  }
1257  // ID was parsed successfuly and the ID is contained within sended suggestions
1258  if (id != null && requestInfo.getSession().isSuggInSendedSuggestions(id)) {
1259  newEntry = new SuggestionLogEntry(tmpId);
1260  // set informations about confirmation
1261  newEntry.setConfirmMethod(method);
1262  newEntry.setConfirmedVersion(retAnnot);
1263  // add to list of confirmed suggestions
1264  if(!requestInfo.getConfirmedSuggestions().contains(newEntry)){
1265  requestInfo.addConfirmedSuggestion(newEntry);
1266  }
1267  }
1268  } else { // the suggestion's not been found
1270  String msg = "Suggestion with the following ID not found: " + tmpId;
1271  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1272  }
1273  }
1274  }
1275 
1276  if (!annotUri.isEmpty()) { // if URI of annotation is available
1277  // get id of annotation from URI (strip off base URI)
1278  String annotIdInStr = annotUri.replace(AppBean.getBaseAnnotUri(), "");
1279  Integer id = null;
1280  try {
1281  id = Integer.parseInt(annotIdInStr);
1282  } catch (NumberFormatException nfe) {
1283  // if id is malformed, handle it as it's not set (it can have unknown base URI)
1284  id = null;
1286  String msg = "Bad id of annotation: " + annotIdInStr;
1287  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1288  }
1289  }
1290  if (id != null) { // if id is available, set it
1291  retAnnot.setId(id);
1292  }
1293  } // if URI of annotation is available
1294 
1295  if (authorId != null) { // if id of author is available
1296  // query database for author (user)
1297  params[0] = "id";
1298  params[1] = authorId;
1299  List uList = AppBean.getPersistenceManager().queryDB("User.findById", params);
1300  if (uList != null && !uList.isEmpty()) { // if user was found
1301  retAnnot.setUser((User) uList.get(0)); // set author of annotation
1302  }
1303  } else if (authorAddress != null && !authorAddress.isEmpty()) {
1304  // if id was not available, but email is available (possible old version of client)
1305  // query database for author (find user by email)
1306  params[0] = "email";
1307  params[1] = authorAddress;
1308  List uList = AppBean.getPersistenceManager().queryDB("User.findByEmail", params);
1309  if (uList != null && !uList.isEmpty()) { // if user was found
1310  retAnnot.setUser((User) uList.get(0)); // set author of annotation
1311  }
1312  // set URI of author
1313  if (retAnnot.getUser() != null) { // if user was set
1314  retAnnot.setAuthorIdStr(AppBean.getBaseAuthorUri() + retAnnot.getUser().getId());
1315  } else { // if user was not found
1316  int langNum = requestInfo.getSession().getLanguageNum();
1317  int lod = requestInfo.getSession().getProtocolLOD();
1318  requestInfo.addError(lod, langNum, Localisation.ERROR_44_ANNOT_AUTHOR, errInfo);
1320  String msg = "Unknowwn author address in annotation and id is not set: " + authorAddress;
1321  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1322  }
1323  return null; // annotation cannot be processed
1324  }
1325  }
1326 
1327  if (retAnnot.getUser() != null && (authorAddress == null || authorAddress.isEmpty())) {
1328  // if author is set but his email doesn't
1329  retAnnot.setAuthorAddress(retAnnot.getUser().getEmail()); // set email
1330  }
1331  if (retAnnot.getUser() != null && (authorName == null || authorName.isEmpty())) {
1332  // if author is set but his full name doesn't
1333  retAnnot.setAuthorName(retAnnot.getUser().getName()); // set author
1334  }
1335 
1336  // get elements with fragments
1337  NodeList fragmentNodes = annotationEl.getElementsByTagName("a:fragment");
1338  int fragmentCnt = fragmentNodes.getLength();
1339  for (int i = 0; i < fragmentCnt; i++) { // for all elements with fragments
1340  Element fragmentEl = (Element) fragmentNodes.item(i);
1341  if (fragmentEl.getParentNode() != annotationEl) {
1342  // if it's fragment of nested annotation at any level
1343  continue; // skip
1344  }
1345  // process element
1346  Fragment fragment = processFragmentEl(fragmentEl, retAnnot, requestInfo);
1347  if (fragment != null) { // if element was successfully processed
1348  retAnnot.addFragment(fragment); // add fragment to annotation
1349  } else { // malformed fragment data - add error message and skip fragment
1350  int langNum = requestInfo.getSession().getLanguageNum();
1351  int lod = requestInfo.getSession().getProtocolLOD();
1352  requestInfo.addError(lod, langNum, Localisation.ERROR_25_BAD_FRAGMENT, errInfo);
1354  String msg = "Bad annotated fragment description.";
1355  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1356  }
1357  }
1358  } // for all elements with fragments
1359 
1360  // get elements with attributes
1361  NodeList attributeNodes = annotationEl.getElementsByTagName("a:attribute");
1362  int attribCnt = attributeNodes.getLength();
1363  for (int i = 0; i < attribCnt; i++) { // for all elements with attributes
1364  Element attributeEl = (Element) attributeNodes.item(i);
1365  if (attributeEl.getParentNode() != annotationEl) {
1366  // if it's attribute of nested annotation at any level
1367  continue; // skip
1368  }
1369  // process element
1370  BaseAttribute attribute = processAttributeEl(attributeEl, retAnnot, requestInfo, i, cMethod);
1371  if (attribute != null) { // if element was successfully processed
1372  retAnnot.addAttribute(attribute); // add attribute to annotation
1373  }
1374  } // for all elements with attributes
1375 
1376  if (newEntry != null && !requestInfo.getConfirmedSuggestions().contains(newEntry)) {
1377  requestInfo.addConfirmedSuggestion(newEntry);
1378  }
1379 
1380  return retAnnot; // return annotation object
1381  } // processAnnotationDescEl()
1382 
1383  /**
1384  * Logs error details connected with processing attribute
1385  *
1386  * @param errAnnotInfo Informations about annotation to reload.
1387  * @param name Name of attribute
1388  * @param type Type of attribute
1389  * @param requestInfo Informations about client request
1390  * @param errorCode Number of error
1391  * @param message Message with additional informations
1392  */
1393  private static void logAttributeError(String errAnnotInfo, String name, String type, RequestInfo requestInfo, int errorCode, String message) {
1394  int langNum = requestInfo.getSession().getLanguageNum();
1395  int lod = requestInfo.getSession().getProtocolLOD();
1396  String info = errAnnotInfo
1397  + "<attribute name=\"" + name + "\" type=\"" + type + "\"/>";
1398  requestInfo.addError(lod, langNum, errorCode, info);
1400  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, message);
1401  }
1402  }
1403 
1404 
1405  /**
1406  * Process element with annotation data.
1407  * If error occurs, generates error message.
1408  *
1409  * @param attributeEl Element with attribute of annotation
1410  * @param annot Annotation to which this attribute belongs
1411  * @param requestInfo Informations about client request
1412  * @param order Order of attribute
1413  * @param cMethod Confirmation method of parent annotation or null
1414  * @return If element was successfully processed, returns attribute, if error occurred, returns null
1415  */
1416  private static BaseAttribute processAttributeEl(Element attributeEl, Annotation annot, RequestInfo requestInfo, int order, Integer cMethod) {
1417  BaseAttribute retAttribute = null;
1418 
1419  // prepare informations about annotation for error message
1420  String errAnnotInfo = "";
1421  if (!(annot.getId() == null)) {
1422  errAnnotInfo = "<reload uri=\"" + annot.getId() + "\"/>";
1423  }
1424 
1425  String name = attributeEl.getAttribute("name");
1426  String type = attributeEl.getAttribute("type");
1427  String priorityStr = attributeEl.getAttribute("priority");
1428  if (name == null) {
1429  name = "";
1430  }
1431  if (type == null) {
1432  type = "";
1433  }
1434  if (name.isEmpty()) { // if name is missing
1435  logAttributeError(errAnnotInfo, name, type, requestInfo,
1437  "Name of attribute of annotation is missing.");
1438  return null; // bad attribute
1439  }
1440 
1441  if (type.isEmpty()) { // if type is missing
1442  logAttributeError(errAnnotInfo, name, type, requestInfo,
1444  "Type of atribute of annotation is missing.");
1445  return null; // bad attribute
1446  }
1447 
1448  Integer priority = null;
1449  if (priorityStr != null) {
1450  try {
1451  priority = Integer.parseInt(priorityStr);
1452  } catch (NumberFormatException ex) {
1453  priority = null;
1454  }
1455  }
1456  if (priority == null) {
1457  priority = order;
1458  }
1459 
1460  // process comment
1461  String attrComment = null;
1462  NodeList attrCommentNL = attributeEl.getElementsByTagName("a:comment");
1463  if (attrCommentNL.getLength() != 0) {
1464  Element attrCommentEl = (Element) attrCommentNL.item(0);
1465  attrComment = MessageProcessor.getElementContent(attrCommentEl);
1466  }
1467 
1468  // in next section of code, stars after comments are used for lucidity (delimiting cases)
1469 
1470  // type specific processing
1471  if (type.contentEquals("person") || type.contentEquals("Person")) {
1472  // if type of attribute is person (user of system) ***********************
1473  // (supported only in old version of clients)
1474 
1475  // get element with informations about user
1476  NodeList personNL = attributeEl.getElementsByTagName("a:person");
1477  Element personEl = (Element) personNL.item(0);
1478  if (personEl != null) { // if element person is presented
1479  String email = "";
1480  String userIdStr = "";
1481  String idInAtt = personEl.getAttribute("id");
1482 
1483  if (idInAtt != null) { // if attribute is not empty
1484  if (idInAtt.contains(AppBean.getBaseAuthorUri())) { // if it's URI
1485  userIdStr = idInAtt.replace(AppBean.getBaseAuthorUri(), "");
1486  } else { // if it's email
1487  email = idInAtt;
1488  }
1489  } // if attribute is not empty
1490 
1491  if (email.isEmpty()) { // if email isn't available, it can be presented in attribute address
1492  // oficially unsupported, but clients can do it
1493  email = personEl.getAttribute("address");
1494  if (email == null) {
1495  email = "";
1496  }
1497  }
1498 
1499  if (email.isEmpty() && userIdStr.isEmpty()) { // if identificator is missing
1500  logAttributeError(errAnnotInfo, name, type, requestInfo,
1502  "Bad attribute of type Person (identificator is missing).");
1503  return null; // bad attribute
1504  }
1505 
1506  Integer userId = null;
1507  if (!userIdStr.isEmpty()) {
1508  // parse user id
1509  try {
1510  userId = Integer.parseInt(userIdStr);
1511  } catch (NumberFormatException nfe) { // if id is malformed
1512  logAttributeError(errAnnotInfo, name, type, requestInfo,
1514  "Bad id of Person in attribute of type Person: " + userIdStr);
1515  return null; // bad attribute
1516  }
1517  }
1518 
1519  // default is find by email
1520  Object[] params = new Object[2];
1521  params[0] = "email";
1522  params[1] = email;
1523  String queryName = "User.findByEmail";
1524 
1525  if (userId != null) { // if id is set, user will be found by id
1526  params[0] = "id";
1527  params[1] = userId;
1528  queryName = "User.findById";
1529  }
1530 
1531  // query database for user
1532  List uList = AppBean.getPersistenceManager().queryDB(queryName, params);
1533  if (uList != null && !uList.isEmpty()) { // if user was found
1534  // create attribute object
1535  retAttribute = new PersonAttribute(name, (User) uList.get(0), annot);
1536  } else { // if user wasn't found, it's bad attribute value
1537  String msg = "Unknown person in attribute of type Person: ";
1538  if (email != null) {
1539  msg += email;
1540  }
1541  if (userId != null) {
1542  msg += userId;
1543  }
1544  logAttributeError(errAnnotInfo, name, type, requestInfo,
1546  return null;
1547  }
1548  } else { // if element person is not presented (value of attribute is empty)
1549  // create attribute object
1550  retAttribute = new PersonAttribute(name, (User) null, annot);
1551  }
1552 
1553  } else if (type.contentEquals("NestedAnnotation") || type.contentEquals("nestedAnnotation")) {
1554  // if type of attribute is nested annotation *****************************
1555 
1556  // get element with nested annotation data
1557  NodeList nestedNL = attributeEl.getElementsByTagName("rdf:Description");
1558  int nCount = nestedNL.getLength();
1559  int ni = 0;
1560  Element nestedEl = (Element) nestedNL.item(ni);
1561  ni++;
1562  if (nestedEl != null) {
1563  while (nestedEl.getParentNode() != attributeEl && ni < nCount) {
1564  // find proper element
1565  nestedEl = (Element) nestedNL.item(ni);
1566  ni++;
1567  }
1568  if (nestedEl.getParentNode() != attributeEl) { // check element
1569  nestedEl = null;
1570  }
1571  }
1572  if (nestedEl == null) { // if element is not found
1573  // try whether element <annotation> is not included
1574  NodeList nestedANL = attributeEl.getElementsByTagName("annotation");
1575  nCount = nestedANL.getLength();
1576  ni = 0;
1577  Element nestedAEl = (Element) nestedANL.item(ni);
1578  ni++;
1579  if (nestedAEl != null) {
1580  while (nestedAEl.getParentNode() != attributeEl && ni < nCount) {
1581  // find proper element
1582  nestedAEl = (Element) nestedANL.item(ni);
1583  ni++;
1584  }
1585  if (nestedAEl.getParentNode() != attributeEl) { // check element
1586  nestedEl = null;
1587  }
1588  }
1589  if (nestedAEl != null) { // if <annotation> element is included
1590  // get element with nested annotation data
1591  NodeList nestedDNL = nestedAEl.getElementsByTagName("rdf:Description");
1592  nCount = nestedDNL.getLength();
1593  ni = 0;
1594  nestedEl = (Element) nestedDNL.item(ni);
1595  ni++;
1596  if (nestedEl != null) {
1597  while (nestedEl.getParentNode() != nestedAEl && ni < nCount) {
1598  // find proper element
1599  nestedEl = (Element) nestedDNL.item(ni);
1600  ni++;
1601  }
1602  if (nestedEl.getParentNode() != nestedAEl) { // check element
1603  nestedEl = null;
1604  }
1605  }
1606  } // if <annotation> element is included
1607  } // if element is not found
1608 
1609  if (nestedEl != null) { // if element with data is presented
1610  // process element with annotation data
1611  Annotation nestedAnnot = processAnnotationDescEl(nestedEl, requestInfo, annot, cMethod);
1612  if (nestedAnnot != null) { // if element was successfully processed
1613  // create attribute object
1614  try {
1615  retAttribute = AttributeManager.createAttribute(name, "NestedAnnotation",
1616  nestedAnnot.getAnnotType(), nestedAnnot, annot);
1617  retAttribute.setAttributeType(nestedAnnot.getAnnotType());
1618  } catch (Exception e) {
1619  String message = e.getMessage();
1620  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1621  return null;
1622  }
1623  } else { // if error occurred - bad attribute value
1624  int langNum = requestInfo.getSession().getLanguageNum();
1625  int lod = requestInfo.getSession().getProtocolLOD();
1626  String info = errAnnotInfo
1627  + "<attribute name=\"" + name + "\" type=\"" + type + "\"/>";
1628  requestInfo.addError(lod, langNum, Localisation.ERROR_7_ATTRIBUTE_VALUE, info);
1630  String msg = "Bad nested annotation.";
1631  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1632  }
1633  return null; // bad attribute
1634  }
1635  } else { // if element with data is not presented - empty attribute value
1636  // create attribute object
1637  try {
1638  retAttribute = AttributeManager.createAttribute(name, "NestedAnnotation", (Annotation) null, annot);
1639  } catch (Exception e) {
1640  String message = e.getMessage();
1641  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1642  return null;
1643  }
1644  }
1645  } else if (type.contentEquals("AnnotationLink") || type.contentEquals("annotationLink")) {
1646  // if type of attribute is link to another annotation ********************
1647 
1648  try {
1649  retAttribute = AttributeManager.createAttribute(name, type, annot);
1650  String value = attributeEl.getAttribute("uri");
1651 
1652 
1653  boolean onlyDigit = true;
1654  if(value != null && !value.equals("")){
1655  //test if string contains only numbers (maybe misplaced tmpId)
1656  int size = value.length();
1657 
1658  for(int i = 0; i < size; i++){
1659  if(!Character.isDigit(value.charAt(i))){
1660  onlyDigit = false;
1661  break;
1662  }
1663  }
1664 
1665  //try to find annotation in DB by tmpId
1666  if(onlyDigit){
1667  ((LinkedAnnotationAttribute) retAttribute).setTmpId(value);
1668  }
1669  }
1670 
1671  if (value != null && !value.equals("") && !onlyDigit) {
1672  // check if is this annotation in DB
1674 
1675  Object[] params = new Object[2];
1676 
1677  try{
1678  String tmpValue = value.replace(AppBean.getBaseAnnotUri(), "");
1679  params[0] = "id";
1680  params[1] = Long.decode(tmpValue);
1681  }
1682 
1683  catch(Exception e){
1684  String message = e.getMessage();
1685  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1686  return null;
1687  }
1688 
1689  finally{
1690  @SuppressWarnings("unchecked")
1691  List<Annotation> annotList = AppBean.getPersistenceManager().queryDB("Annotation.findById",params);
1692  if(annotList == null || annotList.isEmpty()){
1693  String message = "Unknown annotation uri: " + value + ".";
1694  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1695  return null;
1696  }
1697  }
1698  }
1699  retAttribute.setRawValue(value);
1700  } else {
1701  value = attributeEl.getAttribute("tmpId");
1702  if (value != null && !value.equals("")) {
1703  ((LinkedAnnotationAttribute) retAttribute).setTmpId(value);
1704  } else {
1705  retAttribute = AttributeManager.createAttribute(name, "AnyAnnotation", annot);
1706  }
1707  }
1708  } catch (NumberFormatException e) {
1709  String message = "Bad tmpId in annotation link.";
1710  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1711  return null;
1712  } catch (ClassNotFoundException e) {
1713  String message = e.getMessage();
1714  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1715  return null;
1716  } catch (IllegalArgumentException e) {
1717  String message = e.getMessage();
1718  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1719  return null;
1720  } catch (UnsupportedOperationException e) {
1721  int langNum = requestInfo.getSession().getLanguageNum();
1722  int lod = requestInfo.getSession().getProtocolLOD();
1723  requestInfo.addError(lod, langNum, Localisation.ERROR_100_UNKNOWN_ERROR, "", "Internal server error.");
1725  String msg = "UnsupportedOperationException for setting of attribute value.";
1726  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg);
1727  }
1728  } catch (RuntimeException e) {
1729  String message = e.getMessage();
1730  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1731  return null;
1732  }
1733  }
1734  else if(type.contentEquals("Text")){
1735  // if type of attribute is Text ******************************************
1736  NodeList textNodes = attributeEl.getElementsByTagName("a:Content");
1737  String data = null;
1738 
1739  // If correct number of childs are in element.
1740  if(textNodes.getLength() != 1){
1741  String msg = "Zero or more than one CDATA sections in Text attribute.";
1742  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, msg);
1743  return null;
1744  }
1745 
1746  // If element is type of CDATA
1747  else{
1748  Node contentNode = textNodes.item(0);
1749  Node cdataNode = contentNode.getFirstChild();
1750  if (cdataNode != null && cdataNode instanceof CharacterData) {
1751  CharacterData cd = (CharacterData) cdataNode;
1752  try{
1753  data = cd.getData();
1754  }
1755  catch(DOMException e){
1756  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, e.getMessage());
1757  return null;
1758  }
1759  }
1760  }
1761  try {
1762  retAttribute = AttributeManager.createAttribute(name, type, annot);
1763  if (data != null && !data.isEmpty()) {
1764  retAttribute.setRawValue(data);
1765  }
1766  } catch (ClassNotFoundException e) {
1767  String message = e.getMessage();
1768  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1769  return null;
1770  } catch (IllegalArgumentException e) {
1771  String message = e.getMessage();
1772  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1773  return null;
1774  } catch (UnsupportedOperationException e) {
1775  int langNum = requestInfo.getSession().getLanguageNum();
1776  int lod = requestInfo.getSession().getProtocolLOD();
1777  requestInfo.addError(lod, langNum, Localisation.ERROR_100_UNKNOWN_ERROR, "", "Internal server error.");
1779  String msg = "UnsupportedOperationException for setting of attribute value.";
1780  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg);
1781  }
1782  } catch (RuntimeException e) {
1783  String message = e.getMessage();
1784  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1785  return null;
1786  }
1787  }
1788  else if(AttributeManager.containsType(type)){
1789  // other types of attributes *********************************************
1790 
1791  try {
1792  retAttribute = AttributeManager.createAttribute(name, type, annot);
1793  // simple one-field values
1794 
1795  if (!retAttribute.isStructured()) {
1796  String value = attributeEl.getAttribute("rdf:value");
1797  if (!value.isEmpty()) {
1798  retAttribute.setRawValue(value);
1799  }
1800 
1801  // structured attributes
1802  } else {
1803  // get element with point
1804  StructuredAttribute structAttr = (StructuredAttribute) retAttribute;
1805  Node nested = ((Element) attributeEl).getElementsByTagName(structAttr.getXmlAttributeName()).item(0);
1806 
1807  if (nested != null) {
1808  HashMap<String, String> values = new HashMap<String, String>();
1809  NodeList elemValues = ((Element) nested).getChildNodes();
1810  String valueOfAttribute = MessageProcessor.getElementContent(((Element) nested));
1811 
1812  int attrLength = ((Element)nested).getAttributes().getLength();
1813  HashMap<String, String> attributesMap = new HashMap<String, String>();
1814  for(int index = 0; index < attrLength; index++){
1815  String attrName = ((Element)nested).getAttributes().item(index).getNodeName();
1816  String attrValue = ((Element)nested).getAttributes().item(index).getNodeValue();
1817  attributesMap.put(attrName, attrValue);
1818  }
1819 
1820 
1821  for (int i = 0; i < elemValues.getLength(); i++) {
1822  if (elemValues.item(i).getNodeType() == Node.ELEMENT_NODE) {
1823  values.put(elemValues.item(i).getNodeName(), MessageProcessor.getElementContent((Element) elemValues.item(i)));
1824  }
1825  }
1826 
1827  ArrayList<Object> newParam = new ArrayList<Object>(3);
1828  newParam.add(values);
1829  newParam.add(attributesMap);
1830  newParam.add(valueOfAttribute);
1831  ((StructuredAttribute) retAttribute).setRawValues(newParam);
1832  }
1833 
1834  }
1835  } catch (ClassNotFoundException e) {
1836  String message = e.getMessage();
1837  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1838  return null;
1839  } catch (IllegalArgumentException e) {
1840  String message = e.getMessage();
1841  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_7_ATTRIBUTE_VALUE, message);
1842  return null;
1843  } catch (UnsupportedOperationException e) {
1844  int langNum = requestInfo.getSession().getLanguageNum();
1845  int lod = requestInfo.getSession().getProtocolLOD();
1846  requestInfo.addError(lod, langNum, Localisation.ERROR_100_UNKNOWN_ERROR, "", "Internal server error.");
1848  String msg = "UnsupportedOperationException for setting of attribute value.";
1849  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg);
1850  }
1851  } catch (RuntimeException e) {
1852  String message = e.getMessage();
1853  logAttributeError(errAnnotInfo, name, type, requestInfo, Localisation.ERROR_26_ATTRIBUTE_MALFORMED, message);
1854  return null;
1855  }
1856  }
1857  else { // if type of attribute is type of annotation **********************
1858  // It is structured type with empty value. If value will be presented,
1859  // in type field will be linkedAnnotation or nestedAnnotation.
1860  if (!type.contains(AppBean.getBaseTypeUri() + "g")) { // if id of group is not in URI of type
1861  if (type.contains(AppBean.getBaseTypeUri())) {
1862  type = type.replace(AppBean.getBaseTypeUri(), "");
1863  type = AppBean.getBaseTypeUri() + "g" + requestInfo.getSession().getDefaultGroup().getId() + "/" + type;
1864  }
1865  }
1866  Flier flier = requestInfo.getFlier();
1867  AnnotType aType = null;
1868  // query database for type of annotation
1869  Object[] params = new Object[2];
1870  params[0] = "uri";
1871  params[1] = type;
1872  List tList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
1873  if (tList != null && !tList.isEmpty()) { // if type was found
1874  aType = (AnnotType) tList.get(0);
1875  }
1876  else if (flier.getAddedTypes() != null && !flier.getAddedTypes().isEmpty()) {
1877  Iterator<AnnotType> newTypesIt = flier.getAddedTypes().iterator();
1878  while (newTypesIt.hasNext()) {
1879  AnnotType newType = newTypesIt.next();
1880  if (newType.getUri().equals(type)) { // if type was found
1881  aType = newType;
1882  }
1883  }
1884  }
1885  if (aType != null) { // if type was found
1886  // create attribute object of type nested annotation with empty value
1887  try{
1888  retAttribute = AttributeManager.createAttribute(name, "nestedAnnotation", aType, (Annotation)null, annot);
1889  }
1890  catch(ClassNotFoundException e){
1891  int langNum = requestInfo.getSession().getLanguageNum();
1892  int lod = requestInfo.getSession().getProtocolLOD();
1893  String info = errAnnotInfo
1894  + "<attribute name=\"" + name + "\" type=\"" + type + "\"/>";
1895  requestInfo.addError(lod, langNum, Localisation.ERROR_15_ATTRIBUTE_TYPE_UNAVAILABLE, info);
1897  String msg = "Unknown type of attribute: " + type;
1898  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1899  }
1900  return null; // bad attribute
1901  }
1902  } else { // if type was not found - error (unknown type)
1903  int langNum = requestInfo.getSession().getLanguageNum();
1904  int lod = requestInfo.getSession().getProtocolLOD();
1905  String info = errAnnotInfo
1906  + "<attribute name=\"" + name + "\" type=\"" + type + "\"/>";
1907  requestInfo.addError(lod, langNum, Localisation.ERROR_15_ATTRIBUTE_TYPE_UNAVAILABLE, info);
1909  String msg = "Unknown type of attribute: " + type;
1910  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1911  }
1912  return null; // bad attribute
1913  }
1914  } // if type of attribute is type of annotation
1915  retAttribute.setComment(attrComment);
1916  retAttribute.setPriority(priority);
1917  return retAttribute;
1918  } // processAttributeEl()
1919 
1920  /**
1921  * Process element with annotated fragment.
1922  *
1923  * @param fragmentEl Element with annotated fragment
1924  * @param annot Annotation to which this fragment belongs
1925  * @param requestInfo Informations about client request
1926  * @return If element was successfully processed, returns fragment, if error occurred, returns null
1927  */
1928  private static Fragment processFragmentEl(Element fragmentEl, Annotation annot, RequestInfo requestInfo) {
1929  Fragment retFragment = null;
1930 
1931  // get and parse information about validity
1932  String valid = fragmentEl.getAttribute("valid");
1933  Boolean isGood = true;
1934  if (valid != null) {
1935  if (valid.equalsIgnoreCase("false")) {
1936  isGood = false;
1937  }
1938  }
1939 
1940  // get element with XPath
1941  NodeList pathNL = fragmentEl.getElementsByTagName("a:path");
1942  Element pathEl = (Element) pathNL.item(0);
1943  // get XPath of fragment
1944  String path = MessageProcessor.getElementContent(pathEl);
1945 
1946  // get element with offset
1947  NodeList offsetNL = fragmentEl.getElementsByTagName("a:offset");
1948  Element offsetEl = (Element) offsetNL.item(0);
1949  // get offset
1950  String offsetString = MessageProcessor.getElementContent(offsetEl);
1951  // parse offset
1952  Integer offset = null;
1953  if (offsetString != null) {
1954  if (!offsetString.isEmpty()) { // if offset isn't empty
1955  try {
1956  offset = Integer.parseInt(offsetString);
1957  } catch (NumberFormatException nfe) { // malformed offset - bad fragment
1959  String msg = "Bad fragment offset: " + offsetString;
1960  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1961  }
1962  return null; // bad fragment
1963  }
1964  } else { // if offset is empty
1966  String msg = "Empty offset of the fragment.";
1967  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1968  }
1969  return null; // bad fragment
1970  }
1971  }
1972 
1973  // get element with length
1974  NodeList lengthNL = fragmentEl.getElementsByTagName("a:length");
1975  Element lengthEl = (Element) lengthNL.item(0);
1976  // get length
1977  String lengthString = MessageProcessor.getElementContent(lengthEl);
1978  // parse length
1979  Integer length = null;
1980  if (lengthString != null) {
1981  if (!lengthString.isEmpty()) { // if length isn't empty
1982  try {
1983  length = Integer.parseInt(lengthString);
1984  } catch (NumberFormatException nfe) { // malformed length
1986  String msg = "Bad length of the fragment: " + lengthString;
1987  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1988  }
1989  return null; // bad fragment
1990  }
1991  } else { // if length is empty
1993  String msg = "UEmpty length of the fragment.";
1994  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
1995  }
1996  return null; // bad fragment
1997  }
1998  }
1999 
2000  // get element with textual content of fragment
2001  NodeList textNL = fragmentEl.getElementsByTagName("a:annotatedText");
2002  Element textEl = (Element) textNL.item(0);
2003  // get textual content of fragment
2004  String text = MessageProcessor.getElementContent(textEl);
2005  if (text == null) { // if content is not presented (it can be empty, but must be presented)
2007  String msg = "Content of the annotated fragment was not presented.";
2008  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2009  }
2010  return null; // bad fragment
2011  }
2012 
2013  if (text.length() != length.intValue()) { // if length of content don't matching length of fragment
2015  String msg = "Length of the fragment is " + length.intValue()
2016  + " which is not matching to real length of the text \": " + text + "\".";
2017  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2018  }
2019  return null; // bad fragment
2020  }
2021 
2022  // improve XPath to be usable
2023  path = UpdatableFragment.improveXPath(path);
2024  // create fragment object
2025  retFragment = new Fragment(path, offset, length, text, annot, isGood);
2026 
2027  return retFragment;
2028  } // processFragmentEl()
2029 
2030  /**
2031  * Process element with resynchronize message.
2032  * Informations are stored into requestInfo.
2033  * If error occurs, generates error message.
2034  *
2035  * @param resynchronizeEl Element with resynchronize message
2036  * @param requestInfo Informations about client request
2037  */
2038  private static void processResynchronize(Element resynchronizeEl, RequestInfo requestInfo) {
2039  // get element with resynchronized document data
2040  NodeList contentNL = resynchronizeEl.getElementsByTagName("content");
2041  Element contentEl = (Element) contentNL.item(0);
2042  if (contentEl != null) { // if element with data is presented
2043  // get content of resynchronized document
2044  String content = MessageProcessor.getElementContent(contentEl);
2045  if (content == null) { // if content is empty - error
2046  int langNum = requestInfo.getSession().getLanguageNum();
2047  int lod = requestInfo.getSession().getProtocolLOD();
2048  requestInfo.addError(lod, langNum, Localisation.ERROR_23_MISSING_DOCUMENT_CONTENT);
2050  String msg = "Resynchronization with empty content of the document.";
2051  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2052  }
2053  }
2054  requestInfo.setResyncDocContent(content); // set content in requestInfo
2055  } else { // if element with data is not presented - error
2056  int langNum = requestInfo.getSession().getLanguageNum();
2057  int lod = requestInfo.getSession().getProtocolLOD();
2058  requestInfo.addError(lod, langNum, Localisation.ERROR_23_MISSING_DOCUMENT_CONTENT);
2060  String msg = "Resynchronization without content of the document.";
2061  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2062  }
2063  }
2064  } // processResynchronize()
2065 
2066  /**
2067  * Process synchronize message.
2068  * Informations are stored into requestInfo.
2069  * If error occurs, generates error message.
2070  *
2071  * @param synchronizeEl Element with synchronize message
2072  * @param requestInfo Informations about client request
2073  */
2074  private static void processSynchronize(Element synchronizeEl, RequestInfo requestInfo) {
2075  String resource = synchronizeEl.getAttribute("resource");
2076  String linearize = synchronizeEl.getAttribute("linearize");
2077  String overwrite = synchronizeEl.getAttribute("overwrite");
2078  if (resource == null) {
2079  resource = "";
2080  }
2081  if (resource.isEmpty()) { // if URI of resource is empty, error
2082  int langNum = requestInfo.getSession().getLanguageNum();
2083  int lod = requestInfo.getSession().getProtocolLOD();
2084  requestInfo.addError(lod, langNum, Localisation.ERROR_22_MISSING_DOCUMENT_URI);
2086  String msg = "Synchronization without URI of the resource.";
2087  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2088  }
2089  return;
2090  }
2091  // process attribute with linearization
2092  if (linearize.contentEquals("true")) {
2093  requestInfo.setSyncLinearized(true);
2094  }
2095  // process attribute with overwrite (forced synchronization)
2096  if (overwrite.contentEquals("true")) {
2097  requestInfo.setSyncWithOverwrite(true);
2098  }
2099  // get element with synchronized document data
2100  NodeList contentNL = synchronizeEl.getElementsByTagName("content");
2101  Element contentEl = (Element) contentNL.item(0);
2102  if (contentEl != null) { // if element with data is presented
2103  // get content of synchronized document
2104  String content = MessageProcessor.getElementContent(contentEl);
2105  if (content == null) { // if content is empty - error
2106  int langNum = requestInfo.getSession().getLanguageNum();
2107  int lod = requestInfo.getSession().getProtocolLOD();
2108  requestInfo.addError(lod, langNum, Localisation.ERROR_23_MISSING_DOCUMENT_CONTENT);
2110  String msg = "Synchronization with empty content of the document.";
2111  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2112  }
2113  }
2114  // create object with synchronized document
2115  AnnotDocument syncDoc = new AnnotDocument(resource, content);
2116  requestInfo.setSyncDocumentData(syncDoc); // store document into requestInfo
2117  } else { // if element with data is not presented, error
2118  int langNum = requestInfo.getSession().getLanguageNum();
2119  int lod = requestInfo.getSession().getProtocolLOD();
2120  requestInfo.addError(lod, langNum, Localisation.ERROR_23_MISSING_DOCUMENT_CONTENT);
2122  String msg = "Synchronization without content of the document.";
2123  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2124  }
2125  }
2126  } // processSynchronize()
2127 
2128  /**
2129  * Process unsubscribe message (unsubscribe client from sources).
2130  * Client is unsubscribed from sources (no additional operations needed).
2131  * If error occurs, generates error message.
2132  *
2133  * @param unsubscribeEl Element with unsubscribe message
2134  * @param session Client session
2135  * @param requestInfo Informations about client request
2136  */
2137  private static void processUnsubscribe(Element unsubscribeEl, EditorSession session, RequestInfo requestInfo) {
2138  // get list of elements with sources
2139  NodeList sourceNL = unsubscribeEl.getElementsByTagName("source");
2140  int sourceCnt = sourceNL.getLength();
2141  for (int i = 0; i < sourceCnt; i++) { // for each unsubscribed source
2142  Element sourceEl = (Element) sourceNL.item(i);
2143  String type = sourceEl.getAttribute("type");
2144  String user = sourceEl.getAttribute("user");
2145  String uri = sourceEl.getAttribute("uri");
2146  // create object with source description
2147  SubscribedSource source = new SubscribedSource(type, user, uri);
2148  if(!session.containsSource(source) && !session.containsUnsubscribedSource(source)){ //if source isn't subscribed or unsubscribed
2149  session.addUnsubscribeSource(source); //add source in list of unsubscribed sources (black list)
2150  }else {
2151  if(session.containsSource(source) && !session.containsUnsubscribedSource(source)){ //if source is subscribed
2152  session.removeSource(source); //remove source from list of subscribed sources
2153  }
2154  }
2155  } // for each unsubscribed source
2156  } // processUnsubscribe()
2157 
2158  /**
2159  * Process subscribe message (subscribe client to sources).
2160  * Client is subscribed to sources (no additional operations needed).
2161  * If error occurs, generates error message.
2162  *
2163  * @param subscribeEl Element with subscribe message
2164  * @param session Client session
2165  * @param requestInfo Informations about client request
2166  */
2167  private static void processSubscribe(Element subscribeEl, EditorSession session, RequestInfo requestInfo) {
2168  // get list of elements with sources
2169  NodeList sourceNL = subscribeEl.getElementsByTagName("source");
2170  int sourceCnt = sourceNL.getLength();
2171  for (int i = 0; i < sourceCnt; i++) { // for each subscribed source
2172  Element sourceEl = (Element) sourceNL.item(i);
2173  String type = sourceEl.getAttribute("type");
2174  String user = sourceEl.getAttribute("user");
2175  String uri = sourceEl.getAttribute("uri");
2176  if (user != null && !user.isEmpty()) { // if user is presented
2177  if (user.indexOf(AppBean.getBaseAuthorUri()) != 0) { // if base URI isn't presented
2178  // (possibly email supplied)
2179  // query database for user (find by email)
2180  Object[] params = new Object[2];
2181  params[0] = "email";
2182  params[1] = user;
2183  List uList = AppBean.getPersistenceManager().queryDB("User.findByEmail", params);
2184  if (uList != null && !uList.isEmpty()) { // if user is found
2185  User u = (User) uList.get(0);
2186  user = u.getURI(); // get URI of user to source
2187  } else {
2189  String msg = "Subscribe to unknown user's annotations: " + user;
2190  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2191  }
2192  }
2193  } // if base URI isn't presented
2194  } // if user is presented
2195  // create object with source description
2196  SubscribedSource source = new SubscribedSource(type, user, uri);
2197  if(!session.containsUnsubscribedSource(source) && !session.containsSource(source)){ //if source isn't subscribe or unsubscribe
2198  session.addSource(source); // add source to the list of subscribed sources
2199  } else {
2200  if(session.containsUnsubscribedSource(source) && !session.containsSource(source)){ //if source is in unsubscribe list
2201  session.removeUnsubscribeSource(source); // remove source from unsubscribe annotations list
2202  session.addSource(source); // add source to the list of subscribed sources
2203  }
2204  }
2205  } // for each subscribed source
2206  } // processSubscribe()
2207 
2208  /**
2209  * Process settings message.
2210  * Informations are stored into requestInfo.
2211  * If error occurs, generates error message.
2212  *
2213  * @param settingsEl Element with settings message
2214  * @param requestInfo Informations about client request
2215  */
2216  private static void processSettings(Element settingsEl, RequestInfo requestInfo) {
2217  // create new empty list of parameters of user settings
2218  ArrayList<Settings> settings = new ArrayList<Settings>();
2219  // get list of elements with parameters
2220  NodeList paramNL = settingsEl.getElementsByTagName("param");
2221  int paramCnt = paramNL.getLength();
2222  for (int i = 0; i < paramCnt; i++) { // for each parameter
2223  Element paramEl = (Element) paramNL.item(i);
2224  String name = paramEl.getAttribute("name");
2225  String value = paramEl.getAttribute("value");
2226  if (name == null) {
2227  name = "";
2228  }
2229  if (name.isEmpty()) { // if name is empty, parameter is bad
2230  int langNum = requestInfo.getSession().getLanguageNum();
2231  int lod = requestInfo.getSession().getProtocolLOD();
2232  // create error message
2233  requestInfo.addError(lod, langNum, Localisation.ERROR_21_SETTINGS_MALFORMED);
2234  // set old settings to informations about request
2235  // (sent valid actual settings to client)
2236  requestInfo.setSettings(requestInfo.getSession().getSettings());
2238  String msg = "Empty name of parameter of settings.";
2239  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2240  }
2241  return; // if one parameter is bad, whole setting is bad and can't be updated
2242  }
2243  // create object with parameter of user settings
2244  Settings param = new Settings(requestInfo.getSession().getUser(), name, value);
2245  settings.add(param); // add parameter to the new list of parameters
2246  } // for each parameter
2247  // store new list of parameters to the informations about request
2248  requestInfo.setSettings(settings);
2249  } // processSettings()
2250 
2251  /**
2252  * Process refusedSuggestions message (refused suggestions of annotations)
2253  * Informations are stored into requestInfo.
2254  *
2255  * @param refSuggestEl Element with refusedSuggestions message
2256  * @param requestInfo Informations about client request
2257  */
2258  private static void processRefSuggestions(Element refSuggestEl, RequestInfo requestInfo) {
2259  // get elements with informations about suggestions
2260  NodeList rSugNL = refSuggestEl.getElementsByTagName("suggestion");
2261  int rSugNLCnt = rSugNL.getLength();
2262  for (int i = 0; i < rSugNLCnt; i++) { // for each suggestion
2263  Element rSugEl = (Element) rSugNL.item(i);
2264  // get temporary id of suggested annotation
2265  String tmpId = rSugEl.getAttribute("tmpId");
2266  // get refuse method
2267  String methodStr = rSugEl.getAttribute("method");
2268 
2269  // get id of refuse method
2270  int method = Constants.REFUSE_METHODS.indexOf(methodStr);
2271  if (method < 0) { // bad or unknown method
2273  String msg = "Unknown refuse method: " + methodStr;
2274  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2275  }
2276  method = Constants.REFUSED_AUTOMATICALLY; // set to automatically (low confidence)
2277  }
2278  // create reference object for searching in array
2279  SuggestionLogEntry cmp = new SuggestionLogEntry(tmpId);
2280  // find suggested annotation in list of suggestions
2281  if (requestInfo.getSession().getSendedSuggestions() != null && !requestInfo.getSession().getSendedSuggestions().isEmpty()) {
2282  Integer id = null;
2283  try {
2284  id = Integer.parseInt(tmpId);
2285  } catch (NumberFormatException nfe) {
2287  String msg = "The ID of the refused suggestion is not a number: " + tmpId;
2288  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2289  }
2290  }
2291  // ID was parsed successfuly and the ID is contained within sended suggestions
2292  if (id != null && requestInfo.getSession().isSuggInSendedSuggestions(id)) {
2293  SuggestionLogEntry refused = cmp;
2294  // set refuse method
2295  refused.setRefuseMethod(method);
2296  // add refused suggestion to list of just refused suggestions
2297  requestInfo.addRefusedSuggestion(refused);
2298  }
2299  } else { // the suggestion's not been found
2301  String msg = "Suggestion with the following ID not found: " + tmpId;
2302  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2303  }
2304  }
2305  } // for each suggestion
2306  } // processRefSuggestions()
2307 
2308  /**
2309  * Process suggestAnnotations messages (fragments to which are to be suggested
2310  * annotations).
2311  * Informations are stored into session.
2312  * If error occurs, generates error message and turn off suggestions.
2313  * If one message with empty fragment at document beginning is sent, all
2314  * fragments will be discarded and suggestions will be turned off.
2315  * If set of messages is sent, all fragments will be used, but type
2316  * of annotations will be get from first message (fragment) and other
2317  * attributes with type will be discarded.
2318  * New set of fragments (messages) replaces old set of them.
2319  *
2320  * @param suggestMsg List of elements with
2321  * @param requestInfo Informations about client request
2322  */
2323  private static void processSuggestions(NodeList suggestMsg, RequestInfo requestInfo) {
2324  EditorSession session = requestInfo.getSession();
2325  // clear list of fragments to which are to be suggested annotations
2326  session.getSuggestionsFr().clear();
2327  session.clearSuggestionsTypes();
2328  boolean isFirst = true; // first processed message have additional processing
2329  int sugCnt = suggestMsg.getLength();
2330  for (int i = 0; i < sugCnt; i++) { // for all fragments (suggestAnnotations messages)
2331  Element suggestEl = (Element) suggestMsg.item(i);
2332 
2333  Fragment fragment = null;
2334  // get XPath, offset and length
2335  String sPath = suggestEl.getAttribute("path");
2336  String sOffset = suggestEl.getAttribute("offset");
2337  String sLength = suggestEl.getAttribute("length");
2338 
2339  if (sOffset == null) { // not set is a same as empty
2340  sOffset = "";
2341  }
2342  if (sLength == null) {
2343  sLength = "";
2344  }
2345  Integer iSOffset = null;
2346  Integer iSLength = null;
2347  try {
2348  if (!sOffset.isEmpty()) { // if offset is available, parse it
2349  iSOffset = Integer.decode(sOffset);
2350  }
2351  if (!sLength.isEmpty()) { // if length is available, parse it
2352  iSLength = Integer.decode(sLength);
2353  }
2354  // improve XPath to be usable
2355  sPath = UpdatableFragment.improveXPath(sPath);
2356  // create object with fragment
2357  fragment = new Fragment(sPath, iSOffset, iSLength);
2358  } catch (NumberFormatException nfe) { // malformed offset or length - error
2359  int langNum = requestInfo.getSession().getLanguageNum();
2360  int lod = requestInfo.getSession().getProtocolLOD();
2361  requestInfo.addError(lod, langNum, Localisation.ERROR_8_SUG_FRAGMENT);
2363  String msg = "Bad offset or length of fragment for suggestions.";
2364  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg, nfe);
2365  }
2366  }
2367 
2368  if (fragment != null) { // if element was successfully processed
2369  session.addSuggestionsFr(fragment); // add new fragment into session
2370  } else { // if fragment is bad (error occurred)
2371  // clear list of fragments in session (discard suggestions)
2372  session.getSuggestionsFr().clear();
2373  session.clearSuggestionsTypes();
2374  // notify change to appropriate module
2375  requestInfo.setSuggFragmentChanged(true);
2376  return; // end of processing suggestAnnotations
2377  }
2378 
2379  if (isFirst) { // if it's first processed message
2380  // get requested type of annotations
2381  String sType = suggestEl.getAttribute("type");
2382  AnnotType type = null;
2383  if (sType != null && sType.isEmpty()) { // empty attribute is same as if it's not set
2384  sType = null;
2385  }
2386 
2387  if (sType != null) { // if requested type is set
2388  // query database for annotation type
2389  Object[] params = new Object[2];
2390  params[0] = "uri";
2391  params[1] = sType;
2392  List tList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
2393  if (tList != null && !tList.isEmpty()) { // if type was found
2394  type = (AnnotType) tList.get(0);
2395  }
2396  if (type == null) { // if type was not found - error
2397  // clear list of fragments in session (discard suggestions)
2398  session.getSuggestionsFr().clear();
2399  session.clearSuggestionsTypes();
2400  // notify change to appropriate module
2401  requestInfo.setSuggFragmentChanged(true);
2402  // create error message
2403  int langNum = requestInfo.getSession().getLanguageNum();
2404  int lod = requestInfo.getSession().getProtocolLOD();
2405  requestInfo.addError(lod, langNum, Localisation.ERROR_40_BAD_SUGG_TYPE);
2407  String msg = "Request for suggestions of unknown type: " + sType;
2408  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2409  }
2410  return;
2411  }
2412  } // if requested type is set
2413  if (sType != null) {
2414  session.addSuggestionType(sType); // set new requested type to session
2415  }
2416  if (sugCnt == 1) { // if it's only one mesage
2417  if (sPath != null
2418  && (sPath.contentEquals("") || sPath.contentEquals("/"))
2419  && iSOffset != null && iSLength != null
2420  && (iSOffset == 0 && iSLength == 0)) { // if suggestions shall be turned off
2421  // clear list of fragments in session (turn off suggestions)
2422  session.getSuggestionsFr().clear();
2423  session.clearSuggestionsTypes();
2424  }
2425  } // if it's only one mesage
2426  isFirst = false;
2427  } // if it's first processed message
2428  } // for all fragments (suggestAnnotations messages)
2429  requestInfo.setSuggFragmentChanged(true); // notify change to appropriate module
2430  } // processSuggestions()
2431 
2432  /**
2433  * Processes login message (user name or email and password)
2434  * If error occurs, generates error message.
2435  * If password was send in plain text, it will be hashed with MD5.
2436  *
2437  * @param loginEl Element with login message
2438  * @param requestInfo Informations about client request
2439  * @return If message is successfully processed and user credentials are OK, returns user, else returns null
2440  */
2441  private static User processLogin(Element loginEl, RequestInfo requestInfo) {
2442  User user = null;
2443  PersistM persistMan = AppBean.getPersistenceManager();
2444  String userAtt = loginEl.getAttribute("user");
2445  String passAtt = loginEl.getAttribute("password");
2446  String tokenAtt = loginEl.getAttribute("token");
2447  String systemAtt = loginEl.getAttribute("system");
2448  if (userAtt == null) { // null is a same as not set
2449  userAtt = "";
2450  }
2451  if (passAtt == null) {
2452  passAtt = "";
2453  }
2454  if (tokenAtt == null) {
2455  tokenAtt = "";
2456  }
2457  if (systemAtt == null) {
2458  systemAtt = "";
2459  }
2460 
2461  if (!userAtt.isEmpty() && (!tokenAtt.isEmpty() && !systemAtt.isEmpty())) {
2462  // external authentication
2463  String storedToken = AppBean.getExtAuthData(systemAtt, userAtt);
2464  if (storedToken == null) { // token was not found
2465  int langNum = requestInfo.getSession().getLanguageNum();
2466  int lod = requestInfo.getSession().getProtocolLOD();
2467  requestInfo.addError(lod, langNum, Localisation.ERROR_1_BAD_CREDENTIALS);
2469  String msg = "Unknown authentication token received.";
2470  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2471  }
2472  return null;
2473  }
2474  if (!tokenAtt.equals(storedToken)) { // bad token
2475  int langNum = requestInfo.getSession().getLanguageNum();
2476  int lod = requestInfo.getSession().getProtocolLOD();
2477  requestInfo.addError(lod, langNum, Localisation.ERROR_1_BAD_CREDENTIALS);
2479  String msg = "Bad authentication token received.";
2480  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2481  }
2482  return null;
2483  }
2484  Object[] params = new Object[4];
2485  params[0] = "login";
2486  params[1] = userAtt;
2487  params[2] = "comeFrom";
2488  params[3] = systemAtt;
2489  List uList = persistMan.queryDB("User.findByLoginAndSystem", params);
2490  if (uList != null && !uList.isEmpty()) { // if user was found
2491  user = (User) uList.get(0);
2492  }
2493  if (user != null) {
2494  return user;
2495  }
2496  } // external authentication
2497 
2498  if (userAtt.isEmpty() || passAtt.isEmpty()) { // if login (email) or password is not set
2499  int langNum = requestInfo.getSession().getLanguageNum();
2500  int lod = requestInfo.getSession().getProtocolLOD();
2501  requestInfo.addError(lod, langNum, Localisation.ERROR_1_BAD_CREDENTIALS);
2503  String msg = "Login or password is missing.";
2504  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2505  }
2506  return null;
2507  } else { // if credentials are set
2508 
2509  // compute MD5 of password
2510  MessageDigest md5;
2511  String hash = "";
2512  try {
2513  md5 = MessageDigest.getInstance("MD5");
2514  md5.update(passAtt.getBytes());
2515  hash = MessageProcessor.getHexString(md5.digest());
2516  } catch (NoSuchAlgorithmException ex) {
2517  int langNum = requestInfo.getSession().getLanguageNum();
2518  int lod = requestInfo.getSession().getProtocolLOD();
2519  requestInfo.addError(lod, langNum, Localisation.ERROR_100_UNKNOWN_ERROR, "", "Internal server error.");
2521  String msg = "NoSuchAlgorithmException for MD5 algorithm.";
2522  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg, ex);
2523  }
2524  }
2525 
2526  // query database for user (find by login and password)
2527  Object[] params = new Object[4];
2528  params[0] = "login";
2529  params[1] = userAtt;
2530  params[2] = "password";
2531  params[3] = hash; // use MD5 of sent password
2532  List uList = persistMan.queryDB("User.findByCredentials", params);
2533  if (uList != null && !uList.isEmpty()) { // if user was found
2534  user = (User) uList.get(0);
2535  }
2536 
2537  if (user == null) { // user wasn't found, possible secure login
2538  // query database for user (find by login and password)
2539  params[3] = passAtt;
2540  uList = persistMan.queryDB("User.findByCredentials", params);
2541  if (uList != null && !uList.isEmpty()) { // if user was found
2542  user = (User) uList.get(0);
2543  }
2544  }
2545 
2546  if (user == null) { // user wasn't found, possible login with e-mail
2547  params[0] = "email";
2548  params[1] = userAtt;
2549  params[3] = hash; // use MD5 of sent password
2550  uList = persistMan.queryDB("User.findByEmailAndPassword", params);
2551  if (uList != null && !uList.isEmpty()) { // if user was found
2552  user = (User) uList.get(0);
2553  }
2554  }
2555 
2556  if (user == null) { // user wasn't found, possible secure login with e-mail
2557  params[3] = passAtt;
2558  uList = persistMan.queryDB("User.findByEmailAndPassword", params);
2559  if (uList != null && !uList.isEmpty()) { // if user was found
2560  user = (User) uList.get(0);
2561  }
2562  }
2563 
2564  if (user == null) { // user wasn't found - bad credentials
2565  int langNum = requestInfo.getSession().getLanguageNum();
2566  int lod = requestInfo.getSession().getProtocolLOD();
2567  requestInfo.addError(lod, langNum, Localisation.ERROR_1_BAD_CREDENTIALS);
2569  String msg = "Authentication by login and password failed (bad login or password).";
2570  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2571  }
2572  }
2573  } // if credentials are set
2574  return user;
2575  } // processLogin()
2576 
2577  /**
2578  * Process types message (added, changed and removed types of annotations)
2579  * If error occurs, generates error message.
2580  * Informations are stored into requestInfo.
2581  *
2582  * @param typesEl Element with types message
2583  * @param requestInfo Informations about client request
2584  */
2585  private static void processTypes(Element typesEl, RequestInfo requestInfo) {
2586  Flier flier = requestInfo.getFlier();
2587  // get element with added types of annotations
2588  NodeList addTN = typesEl.getElementsByTagName("add");
2589  Element addEl = (Element) addTN.item(0);
2590  if (addEl != null) { // if there are added types
2591  // get elements with types
2592  NodeList addTypeNodes = addEl.getElementsByTagName("type");
2593  int addedTypesCnt = addTypeNodes.getLength();
2594  for (int i = 0; i < addedTypesCnt; i++) { // for each added type
2595  Element addedTypeEl = (Element) addTypeNodes.item(i);
2596  // process element with informations about type of annotation
2597  AnnotType addedType = processTypeEl(addedTypeEl, requestInfo, false);
2598  if (addedType != null) { // if element was successfully processed
2599  // query database for type with same URI
2600  Object[] params = new Object[2];
2601  params[0] = "uri";
2602  params[1] = addedType.getUri();
2603  List tList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
2604  if (tList != null && !tList.isEmpty()) { // if type was found - error
2605  int langNum = requestInfo.getSession().getLanguageNum();
2606  int lod = requestInfo.getSession().getProtocolLOD();
2607  String info = addedType.toXMLStringWA(false);
2608  requestInfo.addError(lod, langNum, Localisation.ERROR_49_DUPLICIT_TYPE, info);
2610  String msg = "Attempt to create of duplicit type of annotation.";
2611  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2612  }
2613  } else { // if type was not found
2614  // If ancestor not exists, but should and name is probably
2615  // composed of path in type tree, breakdown path, set name properly
2616  // and generate ancestors. New names are generated from URI.
2617  breakdownType(addedType, requestInfo);
2618  flier.AddAddedType(addedType); // add new type to flier
2619  }
2620  } // if element was successfully processed
2621  } // for each added type
2622  } // if there are added types
2623 
2624  // get element with changed types of annotations
2625  NodeList updateTN = typesEl.getElementsByTagName("change");
2626  if (updateTN.getLength() == 0) { // if it's not presented, try older version
2627  updateTN = typesEl.getElementsByTagName("update");
2628  }
2629  Element updateEl = (Element) updateTN.item(0);
2630  if (updateEl != null) { // if there are changed types
2631  NodeList updateTypeNodes = updateEl.getElementsByTagName("type");
2632  int updatedTypesCnt = updateTypeNodes.getLength();
2633  for (int i = 0; i < updatedTypesCnt; i++) { // for each changed type
2634  Element updatedTypeEl = (Element) updateTypeNodes.item(i);
2635  // process element with informations about type of annotation
2636  AnnotType updatedType = processTypeEl(updatedTypeEl, requestInfo, true);
2637  if (updatedType != null) { // if element was successfully processed
2638  flier.AddEditedType(updatedType); // add changed type to flier
2639  }
2640  } // for each changed type
2641  } // if there are changed types
2642 
2643  // get element with removed types of annotations
2644  NodeList deleteTN = typesEl.getElementsByTagName("remove");
2645  if (deleteTN.getLength() == 0) { // if it's not presented, try older version
2646  deleteTN = typesEl.getElementsByTagName("delete");
2647  }
2648  Element deleteEl = (Element) deleteTN.item(0);
2649  if (deleteEl != null) { // if there are removed types
2650  NodeList delTypeNodes = deleteEl.getElementsByTagName("type");
2651  int delTypesCnt = delTypeNodes.getLength();
2652  for (int i = 0; i < delTypesCnt; i++) { // for each removed type
2653  Element delTypeEl = (Element) delTypeNodes.item(i);
2654  String delName = delTypeEl.getAttribute("name");
2655  String delAncestor = delTypeEl.getAttribute("ancestor");
2656  String delUri = delTypeEl.getAttribute("uri");
2657  if (delName == null) { // not set is a same as empty
2658  delName = "";
2659  }
2660  if (delUri == null) {
2661  delUri = "";
2662  }
2663  if (delName.isEmpty() || delUri.isEmpty()) { // if name or URI is empty
2664  String info = "";
2665  // create appropriate error message
2666  if (!delName.isEmpty()) {
2667  info = "<type name=\"" + delName + "\"/>";
2668  } else if (!delUri.isEmpty()) {
2669  info = "<type uri=\"" + delUri + "\"/>";
2670  }
2671  int langNum = requestInfo.getSession().getLanguageNum();
2672  int lod = requestInfo.getSession().getProtocolLOD();
2673  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, info);
2675  String msg = "Attempt to remove type of annotation without name or URI: " + info;
2676  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2677  }
2678  } else { // if all required informations are available
2679  // query database for type of annotation
2680  Object[] params = new Object[2];
2681  params[0] = "uri";
2682  params[1] = delUri;
2683  List dList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
2684  if (dList != null && !dList.isEmpty()) { // if type was found
2685  // query database for annotations of this type
2686  AnnotType dType = (AnnotType) dList.get(0);
2687  params[0] = "type";
2688  params[1] = dType.getId();
2689  List aList = AppBean.getPersistenceManager().queryDB("Annotation.findByType", params);
2690  if (aList != null && !aList.isEmpty()) { // if annotations was found
2691  // error - forbidden operation
2692  int langNum = requestInfo.getSession().getLanguageNum();
2693  int lod = requestInfo.getSession().getProtocolLOD();
2694  String info = "<type name=\"" + delName + "\" ancestor=\"" + delAncestor + "\" uri=\"" + delUri + "\"/>";
2695  requestInfo.addError(lod, langNum, Localisation.ERROR_47_USED_TYPE_DEL, info);
2697  String msg = "Attempt to delete used type of annotation: " + delUri;
2698  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2699  }
2700  } else { // if annotations of this type was not found
2701  // query database for subtypes of this type of annotation
2702  params[0] = "ancestor";
2703  params[1] = dType.getId();
2704  List aTList = AppBean.getPersistenceManager().queryDB("AnnotType.findByAncestor", params);
2705  if (aTList != null && !aTList.isEmpty()) { // if subtypes was found
2706  // error - forbidden operation
2707  int langNum = requestInfo.getSession().getLanguageNum();
2708  int lod = requestInfo.getSession().getProtocolLOD();
2709  String info = "<type name=\"" + delName + "\" ancestor=\"" + delAncestor + "\" uri=\"" + delUri + "\"/>";
2710  requestInfo.addError(lod, langNum, Localisation.ERROR_51_TYPE_W_SUBTYPE_DEL, info);
2712  String msg = "Attempt to delete type of annotation with subtypes: " + delUri;
2713  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2714  }
2715  } else { // if subtypes was not found
2716  flier.AddRemovedType(dType); // add type to list of removed types in flier
2717  }
2718  } // if annotations of this type was not found
2719  } else { // if type was not found - error
2720  int langNum = requestInfo.getSession().getLanguageNum();
2721  int lod = requestInfo.getSession().getProtocolLOD();
2722  String info = "<type name=\"" + delName + "\" ancestor=\"" + delAncestor + "\" uri=\"" + delUri + "\"/>";
2723  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, info);
2725  String msg = "Attempt to delete unknown type of annotation: " + delUri;
2726  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2727  }
2728  }
2729  } // if all required informations are available
2730  } // for each removed type
2731  } // if there are removed types
2732  } // processTypes()
2733 
2734  /**
2735  * If ancestor of type of annotation is not exists, but should and name
2736  * is probably composed of path in type tree, this method breakdowns path,
2737  * sets name properly and generate ancestors.
2738  * New names are generated from URI.
2739  * Ancestors are stored into informations about client request.
2740  *
2741  * @param type Type of annotation to check and breakdown
2742  * @param requestInfo Informations about client request
2743  */
2744  public static void breakdownType(AnnotType type, RequestInfo requestInfo) {
2745  Flier flier = requestInfo.getFlier();
2746  // get user group to which this type belongs
2747  UserGroup group = type.getGroup();
2748  // get string with name of type and names of his ancestors
2749  String namesStr = type.getUri().replace(AppBean.getBaseTypeUri(), "");
2750  // get array with name of type and names of his ancestors
2751  String[] namesArr = namesStr.split("/");
2752  ArrayList<String> names = new ArrayList<String>(Arrays.asList(namesArr));
2753  int nSize = names.size(); // compute number of names
2754  if (nSize > 2) { // if there is more then name of type and id of group
2755  // get name of type and remove it from list
2756  String typeName = names.remove(nSize - 1);
2757  nSize--;
2758  type.setName(typeName); // set proper name to type
2759  AnnotType nextType = type; // set actually checked type to checked type
2760  while (nSize > 1) { // create ancestor types (last name is group name)
2761  // get name of actual (next to now generated) type
2762  String nextName = nextType.getName();
2763  // get name of ancestor (previous in hierarchy)
2764  String prevName = names.remove(nSize - 1);
2765  nSize--;
2766  // get URI of actual type
2767  String nUri = nextType.getUri();
2768  // get URI of ancestor type
2769  // prevUri = uri of next without "/" and name of next
2770  String prevUri = nUri.substring(0, nUri.lastIndexOf("/"));
2771  // flag represents a successful search for a type in the newTypes array
2772  boolean foundInNewTypes = false;
2773 
2774  // query database for ancestor type
2775  Object[] params = new Object[2];
2776  params[0] = "uri";
2777  params[1] = prevUri;
2778  List tList = AppBean.getPersistenceManager().queryDB("AnnotType.findByUri", params);
2779  if (tList != null && !tList.isEmpty()) { // if ancestor was found
2780  AnnotType prevType = (AnnotType) tList.get(0);
2781  nextType.setAncestorType(prevType); // set ancestor properly
2782  nextType.addAncestorType(prevType);
2783  break; // end of checking (all other is in database)
2784  }
2785  else if (flier.getAddedTypes() != null && !flier.getAddedTypes().isEmpty()) {
2786  Iterator<AnnotType> newTypesIt = flier.getAddedTypes().iterator();
2787  while (newTypesIt.hasNext()) {
2788  AnnotType newType = newTypesIt.next();
2789  if (newType.getUri().equals(prevUri)) {
2790  nextType.setAncestorType(newType); // set ancestor properly
2791  nextType.addAncestorType(newType);
2792  foundInNewTypes = true;
2793  break;
2794  }
2795  }
2796  }
2797 
2798  // if not found in DB nor newTypes, create ancestor type
2799  if (!foundInNewTypes) {
2800  // create ancestor type
2801  AnnotType newType = new AnnotType(prevUri, prevName, null, group);
2802  nextType.setAncestorType(newType); // set ancestor of actual type to new ancestor
2803  nextType.addAncestorType(newType);
2804  flier.AddAddedType(newType); // add new ancestor type to flier
2805  nextType = newType; // set ancestor as actually checked type
2806  }
2807  } // create ancestor types (last name is group name)
2808  } // if there is more then name of type and id of group
2809  } // breakdownType()
2810 
2811  /**
2812  * Process element with request for entities
2813  *
2814  * @param entityReqEl Element with informations about request
2815  * @param requestInfo Informations about client request
2816  */
2817  private static void processEntityRequest(Element entityReqEl, RequestInfo requestInfo){
2818 
2819  String type = entityReqEl.getAttribute("type");
2820  String filter = entityReqEl.getAttribute("filter");
2821 
2822  if(filter.isEmpty()){
2823  int langNum = requestInfo.getSession().getLanguageNum();
2824  int lod = requestInfo.getSession().getProtocolLOD();
2825  requestInfo.addError(lod, langNum, Localisation.ERROR_63_EMPTY_ENTITY_FILTER);
2826 
2827  requestInfo.setSettings(requestInfo.getSession().getSettings());
2829  String msg = "Empty filter of parameter of dictionary request.";
2830  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2831  }
2832 
2833  return;
2834  }
2835  requestInfo.setEntityRequest(new RequestInfo.EntityRequest(type,filter));
2836  } // processEntityRequest()
2837 
2838  /**
2839  * Process element with informations about type of annotation
2840  * If error occurs, generates error message.
2841  *
2842  * @param typeEl Element with informations about type of annotation
2843  * @param requestInfo Informations about client request
2844  * @param update If this is updated type (may be found in database), then true, if it's new type, then false
2845  * @return If element was successfully processed, returns type of annotation, if error occurred, returns null
2846  */
2847  private static AnnotType processTypeEl(Element typeEl, RequestInfo requestInfo, boolean update) {
2848  AnnotType retType = null;
2849  String name = typeEl.getAttribute("name");
2850  String ancestor = typeEl.getAttribute("ancestor");
2851  String uri = typeEl.getAttribute("uri");
2852  String group = typeEl.getAttribute("group");
2853  if (name == null) { // not set is a same as empty
2854  name = "";
2855  }
2856  if (uri == null) {
2857  uri = "";
2858  }
2859  if (ancestor == null) {
2860  ancestor = "";
2861  }
2862  if (name.isEmpty()) { // if name is empty - error
2863  int langNum = requestInfo.getSession().getLanguageNum();
2864  int lod = requestInfo.getSession().getProtocolLOD();
2865  if (update) {
2866  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN);
2868  String msg = "Empty name of updated type of annotation.";
2869  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2870  }
2871  } else {
2872  requestInfo.addError(lod, langNum, Localisation.ERROR_16_TYPE_MALFORMED);
2874  String msg = "New type of annotation without name.";
2875  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
2876  }
2877  }
2878  return null; // bad type
2879  }
2880 
2881  PersistM pm = AppBean.getPersistenceManager();
2882  Object[] params = new Object[2]; // parameters for database queries
2883 
2884  Integer groupId = null;
2885  if (group != null && !group.isEmpty()) { // if URI of user group is set
2886  // get id of group by stripping off base URI
2887  String groupIdStr = group.replace(AppBean.getBaseGroupUri(), "");
2888  // parse id of group
2889  try {
2890  groupId = Integer.parseInt(groupIdStr);
2891  } catch (NumberFormatException nfe) { // if id of group is malformed
2892  // create error message
2893  int langNum = requestInfo.getSession().getLanguageNum();
2894  int lod = requestInfo.getSession().getProtocolLOD();
2895  String info = "<group id=\"" + group + "\"/>";
2896  requestInfo.addError(lod, langNum, Localisation.ERROR_46_UNKNOWN_GROUP_TYPE, info);
2898  String msg = "Bad group in type of annotation: " + groupIdStr;
2899  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg, nfe);
2900  }
2901  // set group by another method
2902  groupId = null;
2903  }
2904  } // if URI of user group is set
2905 
2906  if (groupId == null) { // if URI of user group is not set
2907  if (uri.contains(AppBean.getBaseTypeUri() + "g")) { // if id of group is in URI of type
2908  // get id of group and list of names by stripping off base URI
2909  String groupIdStr = uri.replace(AppBean.getBaseTypeUri() + "g", "");
2910  // find beginning of list of names
2911  int index = groupIdStr.indexOf("/");
2912  if (index > 0) { // if beginning of list of names was found (URI is not malformed)
2913  // get id of group by stripping off list of names
2914  groupIdStr = groupIdStr.substring(0,index);
2915  // parse id of group
2916  try {
2917  groupId = Integer.parseInt(groupIdStr);
2918  } catch (NumberFormatException nfe) { // if id of group is malformed
2919  // create error message
2920  int langNum = requestInfo.getSession().getLanguageNum();
2921  int lod = requestInfo.getSession().getProtocolLOD();
2922  String info = "<group id=\"" + group + "\"/>";
2923  requestInfo.addError(lod, langNum, Localisation.ERROR_46_UNKNOWN_GROUP_TYPE, info);
2925  String msg = "Bad group in URI of type of annotation: " + groupIdStr;
2926  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg, nfe);
2927  }
2928  // set group by another method
2929  groupId = null;
2930  }
2931  } // if beginning of list of names was found
2932  } // if id of group is in URI of type
2933  } // if URI of user group is not set
2934 
2935  // if id of user group is empty, but URI of ancestor is not empty
2936  if (groupId == null && ancestor != null && !ancestor.isEmpty()) {
2937  if (ancestor.contains(AppBean.getBaseTypeUri() + "g")) { // if URI of ancestor contains id of group
2938  // get id of group and list of names by stripping off base URI
2939  String groupIdStr = ancestor.replace(AppBean.getBaseTypeUri() + "g", "");
2940  // find beginning of list of names
2941  int index = groupIdStr.indexOf("/");
2942  if (index > 0) { // if beginning of list of names was found (URI is not malformed)
2943  // get id of group by stripping off list of names
2944  groupIdStr = groupIdStr.substring(0,index);
2945  // parse id of group
2946  try {
2947  groupId = Integer.parseInt(groupIdStr);
2948  } catch (NumberFormatException nfe) { // if id of group is malformed
2949  // create error message
2950  int langNum = requestInfo.getSession().getLanguageNum();
2951  int lod = requestInfo.getSession().getProtocolLOD();
2952  String info = "<group id=\"" + group + "\"/>";
2953  requestInfo.addError(lod, langNum, Localisation.ERROR_46_UNKNOWN_GROUP_TYPE, info);
2955  String msg = "Bad group in ancestor type of annotation: " + groupIdStr;
2956  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg, nfe);
2957  }
2958  // set group by another method
2959  groupId = null;
2960  }
2961  } // if beginning of list of names was found
2962  } // if URI of ancestor contains id of group
2963  } // if id of user group is empty, but URI of ancestor is not empty
2964 
2965  if (groupId == null) { // if URI of user group is still not set
2966  if (MessageProcessor.isGroupIncluded(name)) { // if id of group is in linearized name
2967  // get id of group and list of names by stripping off "g"
2968  String groupIdStr = uri.replace("g", "");
2969  // replace arrows
2970  groupIdStr = MessageProcessor.replaceArrows(groupIdStr);
2971  // find beginning of list of names
2972  int index = groupIdStr.indexOf("/");
2973  if (index > 0) { // if beginning of list of names was found
2974  // get id of group by stripping off list of names
2975  groupIdStr = groupIdStr.substring(0,index);
2976  // parse id of group
2977  try {
2978  groupId = Integer.parseInt(groupIdStr);
2979  int index1 = name.indexOf("-> ");
2980  int index2 = name.indexOf("->");
2981  if (index1 < index2 && index1 > 0) { // if first arrow is followed by space
2982  // strip off group
2983  name = name.substring(index1 + 3);
2984  } else if (index2 > 0) { // if first arrow is not followed by space
2985  // strip off group
2986  name = name.substring(name.indexOf("->") + 2);
2987  } else { // if it's not id of group
2988  // set group by another method
2989  groupId = null;
2990  }
2991  } catch (NumberFormatException nfe) { // if it's not id of group
2992  // set group by another method
2993  groupId = null;
2994  } catch (Exception e) { // if it's not id of group
2995  // set group by another method
2996  groupId = null;
2997  }
2998  } // if beginning of list of names was found
2999  } // if id of group is in linearized name
3000  } // if URI of user group is still not set
3001 
3002  UserGroup uGroup = null;
3003  if (groupId != null) { // if id of user group is available
3004  // query database for user group
3005  params[0] = "id";
3006  params[1] = groupId;
3007  List gList = AppBean.getPersistenceManager().queryDB("UserGroup.findById", params);
3008  Settings groupParam = null;
3009  if (gList != null && !gList.isEmpty()) { // if group was found
3010  uGroup = (UserGroup) gList.get(0);
3011  } else { // if group was not found
3012  // set to default group
3013  uGroup = null;
3014  // create error message
3015  int langNum = requestInfo.getSession().getLanguageNum();
3016  int lod = requestInfo.getSession().getProtocolLOD();
3017  String info = "<group id=\"" + AppBean.getBaseGroupUri() + groupId + "\"/>";
3018  requestInfo.addError(lod, langNum, Localisation.ERROR_46_UNKNOWN_GROUP_TYPE, info);
3020  String msg = "Unknown user group in the type of annotation: " + info;
3021  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3022  }
3023  }
3024  } // if id of user group is available
3025 
3026  if (uGroup == null) { // if user group is not available, set to default
3027  uGroup = requestInfo.getSession().getDefaultGroup();
3028  }
3029 
3030  if (uGroup == null) { // if user group is still null (all attempts failed)
3031  // print error message
3032  int langNum = requestInfo.getSession().getLanguageNum();
3033  int lod = requestInfo.getSession().getProtocolLOD();
3034  String info = "<type name=\"" + name + "\"/>";
3035  requestInfo.addError(lod, langNum, Localisation.ERROR_45_UNKNOWN_GROUP, info);
3037  String msg = "All attempts to getting of user group for type of annotation failed.";
3038  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3039  }
3040  return null; // bad type of annotation
3041  }
3042 
3043  AnnotType ancestorType = null;
3044  if (!ancestor.isEmpty()) { // if type have URI of ancestor set
3045  if (!ancestor.contains(AppBean.getBaseTypeUri() + "g")
3046  && ancestor.contains(AppBean.getBaseTypeUri())) {
3047  ancestor = ancestor.substring(0, AppBean.getBaseTypeUri().length())
3048  + "g" + requestInfo.getSession().getDefaultGroup().getId() + "/"
3049  + ancestor.substring(AppBean.getBaseTypeUri().length(),ancestor.length());
3050  }
3051  // query database for ancestor
3052  params[0] = "uri";
3053  params[1] = ancestor;
3054  List aList = pm.queryDB("AnnotType.findByUri", params);
3055  if (aList != null && !aList.isEmpty()) { // if ancestor was found
3056  ancestorType = (AnnotType) aList.get(0);
3057  } else { // if ancestor was not found
3058  // it possibly can be new type
3059  Iterator<AnnotType> atIter = (Iterator<AnnotType>) requestInfo.getFlier().getAddedTypes().iterator();
3060  while (atIter.hasNext() && ancestorType == null) { // look over just added types
3061  AnnotType addedT = atIter.next();
3062  if (addedT.getUri().equals(ancestor)) { // if type was found
3063  ancestorType = addedT;
3064  }
3065  }
3066  if (ancestorType == null) { // if ancestor is not new type
3067  // create appropriate error message
3068  int langNum = requestInfo.getSession().getLanguageNum();
3069  int lod = requestInfo.getSession().getProtocolLOD();
3070  String info = "<type name=\"" + name + "\" uri=\"" + uri + "\"/>";
3071  if (update) {
3072  requestInfo.addError(lod, langNum, Localisation.ERROR_18_BAD_EDITED_TYPE, info);
3074  String msg = "Bad ancestor type in updated type of annotation: " + info;
3075  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3076  }
3077  } else {
3078  requestInfo.addError(lod, langNum, Localisation.ERROR_16_TYPE_MALFORMED, info);
3080  String msg = "Bad ancestor type in new type of annotation: " + info;
3081  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3082  }
3083  }
3084  return null; // bad type
3085  } // if ancestor is not new type
3086  } // if ancestor was not found
3087  } // if type have URI of ancestor set
3088 
3089  if (uri.isEmpty() && update) { // if URI of type of annotation is empty and it's update of type
3090  // create error message
3091  int langNum = requestInfo.getSession().getLanguageNum();
3092  int lod = requestInfo.getSession().getProtocolLOD();
3093  String info = "<type name=\"" + name + "\"/>";
3094  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, info);
3096  String msg = "Attempt to update type of annotation without URI.";
3097  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3098  }
3099  return null; // type cannot be updated
3100  }
3101 
3102  AnnotType qType = null;
3103  if (update) { // if it's update of type
3104  // query database for updated type
3105  params[0] = "uri";
3106  params[1] = uri;
3107  List utList = pm.queryDB("AnnotType.findByUri", params);
3108  if (utList != null && !utList.isEmpty()) { // if type was found
3109  qType = (AnnotType) utList.get(0);
3110  } else { // if updated type was not found - error
3111  int langNum = requestInfo.getSession().getLanguageNum();
3112  int lod = requestInfo.getSession().getProtocolLOD();
3113  String info = "<type name=\"" + name + "\" ancestor=\"" + ancestor + "\" uri=\"" + uri + "\"/>";
3114  requestInfo.addError(lod, langNum, Localisation.ERROR_19_TYPE_UNKNOWN, info);
3116  String msg = "Unknown type of annotation for update: " + info;
3117  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3118  }
3119  return null; // type cannot be updated
3120  }
3121 
3122  if (!qType.getName().equals(name)) {
3123  // if name was changed, error - forbidden operation
3124  int langNum = requestInfo.getSession().getLanguageNum();
3125  int lod = requestInfo.getSession().getProtocolLOD();
3126  String info = "<type name=\"" + name + "\" uri=\"" + uri + "\"/>";
3127  requestInfo.addError(lod, langNum, Localisation.ERROR_20_TYPE_NAME_MODIFY, info);
3129  String msg = "Attempt to change name of the type of annotation: "
3130  + qType.getName() + " - " + name;
3131  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3132  }
3133  return null; // type cannot be updated
3134  }
3135 
3136  if (qType.getGroup() != null) {
3137  if (!qType.getGroup().equals(uGroup)) {
3138  // if group was changed, error - forbidden operation
3139  int langNum = requestInfo.getSession().getLanguageNum();
3140  int lod = requestInfo.getSession().getProtocolLOD();
3141  String info = "<type name=\"" + name + "\" uri=\"" + uri + "\"/>";
3142  requestInfo.addError(lod, langNum, Localisation.ERROR_20_TYPE_NAME_MODIFY, info);
3144  String msg = "Attempt to change group of the type of annotation.";
3145  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3146  }
3147  return null; // type cannot be updated
3148  }
3149  } else {
3151  String msg = "Type of annotation without the user group..";
3152  Logger.getLogger(MessageProcessor.class.getName()).log(Level.SEVERE, msg);
3153  }
3154  }
3155 
3156  if (qType.getAncestorType() != null) { // if ancestor of updated type is not null
3157  if (!ancestor.equals(qType.getAncestorType().getUri())) {
3158  // if ancestor was changed, error - forbidden operation
3159  int langNum = requestInfo.getSession().getLanguageNum();
3160  int lod = requestInfo.getSession().getProtocolLOD();
3161  String info = "<type name=\"" + name + "\" ancestor=\"" + qType.getAncestorType().getUri() + "\" uri=\"" + uri + "\"/>";
3162  requestInfo.addError(lod, langNum, Localisation.ERROR_20_TYPE_NAME_MODIFY, info);
3164  String msg = "Attempt to change ancestor type of annotation.";
3165  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3166  }
3167  return null; // type cannot be updated
3168  }
3169  } else if (!ancestor.isEmpty()) { // if client is trying to set ancestor which is null
3170  // error - forbidden operation
3171  int langNum = requestInfo.getSession().getLanguageNum();
3172  int lod = requestInfo.getSession().getProtocolLOD();
3173  String info = "<type name=\"" + name + "\" ancestor=\"\" uri=\"" + uri + "\"/>";
3174  requestInfo.addError(lod, langNum, Localisation.ERROR_20_TYPE_NAME_MODIFY, info);
3176  String msg = "Attempt to change ancestor type of annotation.";
3177  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3178  }
3179  return null; // type cannot be updated
3180  }
3181  } // if it's update of type
3182 
3183  // process comment
3184  String comment = null;
3185  NodeList commentNL = typeEl.getElementsByTagName("comment");
3186  if (commentNL.getLength() != 0) {
3187  Element commentEl = (Element) commentNL.item(0);
3188  comment = MessageProcessor.getElementContent(commentEl);
3189  }
3190 
3191  // create object with informations about type
3192  // it's necessary in case of update too (can't directly modify original type)
3193  retType = new AnnotType(uri, name, ancestorType, uGroup);
3194 
3195  retType.setComment(comment); // set comment
3196 
3197  // if URI is missing, create it from linearized name, ancestor and user group
3198  if (!update && uri.isEmpty()) {
3199  uri = retType.getGeneratedURI();
3200  retType.setUri(uri);
3201  }
3202 
3203  if (!uri.equals(retType.getGeneratedURI())) { // if URI is bad
3204  int langNum = requestInfo.getSession().getLanguageNum();
3205  int lod = requestInfo.getSession().getProtocolLOD();
3206  String info = "<type name=\"" + name + "\" uri=\"" + uri + "\"/>";
3207  requestInfo.addError(lod, langNum, Localisation.ERROR_56_BAD_ANNOT_TYPE_URI, info);
3209  String msg = "URI of type of annotation is not matching to generated one: "
3210  + uri + " != " + retType.getGeneratedURI();
3211  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3212  }
3213  return null; // type cannot be added or updated
3214  }
3215 
3216  // create list for attributes
3217  ArrayList<AnnotTypeAttr> newAttrs = new ArrayList<AnnotTypeAttr>();
3218  // get elements with attributes
3219  NodeList attNodes = typeEl.getElementsByTagName("attribute");
3220  int attNCnt = attNodes.getLength(); // count attributes
3221  NodeList attNodes2 = typeEl.getElementsByTagName("a:attribute"); // second variant
3222  int attNCnt2 = attNodes2.getLength(); // count attributes
3223  if (attNCnt2 > 0 && attNCnt == 0) { // switch to second variant
3224  attNCnt = attNCnt2;
3225  attNodes = attNodes2;
3226  }
3227  // create beginning of information about type for errors
3228  String groupsS = "";
3229  if (uGroup != null) {
3230  groupsS = " group=\"" + uGroup.getUri() + "\"";
3231  }
3232  String errInfo = "<type name=\"" + name + "\" uri=\"" + uri + "\"" + groupsS + ">";
3233 
3234  int errCnt = 0; // error counter
3235  ArrayList<String> namesArr = new ArrayList<String>(); // used names
3236  ArrayList<String> namesTypesArr = new ArrayList<String>(); // used names and types
3237  // process attributes of type of annotation
3238  for (int i = 0; i < attNCnt; i++) { // for each attribute element
3239  Element attrEl = (Element) attNodes.item(i);
3240  String attrName = attrEl.getAttribute("name");
3241  String attrType = attrEl.getAttribute("type");
3242  String priorityStr = attrEl.getAttribute("priority");
3243  String attrRequiredStr = attrEl.getAttribute("required");
3244  Boolean attrRequired = Boolean.parseBoolean(attrRequiredStr);
3245 
3246  Integer priority = null;
3247  if (priorityStr != null) {
3248  try {
3249  priority = Integer.parseInt(priorityStr);
3250  } catch (NumberFormatException ex) {
3251  priority = null;
3252  }
3253  }
3254  if (priority == null) {
3255  priority = i;
3256  }
3257 
3258  // process comment
3259  String attrComment = null;
3260  NodeList attrCommentNL = attrEl.getElementsByTagName("comment");
3261  if (attrCommentNL.getLength() != 0) {
3262  Element attrCommentEl = (Element) attrCommentNL.item(0);
3263  attrComment = MessageProcessor.getElementContent(attrCommentEl);
3264  }
3265  attrCommentNL = attrEl.getElementsByTagName("a:comment");
3266  if (attrComment == null && attrCommentNL.getLength() != 0) {
3267  Element attrCommentEl = (Element) attrCommentNL.item(0);
3268  attrComment = MessageProcessor.getElementContent(attrCommentEl);
3269  }
3270 
3271  if (Constants.SIMPLE_TYPES.contains(attrType)) { // if it's simple type
3272  // create object with attribute of type of annotation
3273  AnnotTypeAttr newAttr = new AnnotTypeAttr(retType, attrName, attrType, attrRequired);
3274  newAttr.setPriority(priority);
3275  newAttr.setComment(attrComment); // set comment
3276  if (namesArr.contains(attrName)) { // duplicit attribute
3277  int index = namesArr.indexOf(attrName);
3278  if (namesTypesArr.get(index).equals(attrName + attrType)) {
3279  continue; // skip duplicity
3280  }
3281  errInfo = errInfo.concat("<attribute name=\"" + attrName + "\" type=\""
3282  + attrType + "\"/>");
3283  errCnt++; // increase error count and skip attribute
3285  String msg = "Duplicit attribute of the type of annotation.";
3286  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3287  }
3288  } else {
3289  newAttrs.add(newAttr); // add attribute to the list of attributes
3290  namesArr.add(attrName); // add name to the list of names
3291  namesTypesArr.add(attrName + attrType);
3292  }
3293  } else { // if it's structured type
3294  // query database for type of attribute (type of annotation)
3295  params[0] = "uri";
3296  params[1] = attrType;
3297  List tList = pm.queryDB("AnnotType.findByUri", params);
3298  if (tList != null && !tList.isEmpty()) { // if type was found
3299  AnnotType attrStructType = (AnnotType) tList.get(0);
3300  // create object with attribute of type of annotation
3301  AnnotTypeAttr newAttr = new AnnotTypeAttr(retType, attrName, attrStructType, attrRequired);
3302  newAttr.setPriority(priority);
3303  newAttr.setComment(attrComment); // set comment
3304  if (namesArr.contains(attrName)) { // duplicit attribute
3305  int index = namesArr.indexOf(attrName);
3306  if (namesTypesArr.get(index).equals(attrName + attrType)) {
3307  continue; // skip duplicity
3308  }
3309  errInfo = errInfo.concat("<attribute name=\"" + attrName + "\" type=\""
3310  + attrType + "\"/>");
3311  errCnt++; // increase error count and skip attribute
3313  String msg = "Duplicit attribute of the type of annotation.";
3314  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3315  }
3316  } else {
3317  newAttrs.add(newAttr); // add attribute to the list of attributes
3318  namesArr.add(attrName); // add name to the list of names
3319  namesTypesArr.add(attrName + attrType);
3320  }
3321  } else { // if type was not found - error
3322  errInfo = errInfo.concat("<attribute name=\"" + attrName + "\" type=\""
3323  + attrType + "\"/>");
3324  errCnt++; // increase error count and skip attribute
3326  String msg = "Unknown structured type of attribute of the type of annotation: " + attrType;
3327  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3328  }
3329  }
3330  } // if it's structured type
3331  } // for each attribute element
3332 
3333  int ancErrCnt = 0; // error counter
3334  // create list for ancestors
3335  ArrayList<AnnotType> newAncestors = new ArrayList<AnnotType>();
3336  // get elements with ancestors
3337  NodeList ancNodes = typeEl.getElementsByTagName("ancestor");
3338  int ancNCnt = ancNodes.getLength(); // count ancestors
3339  // process ancestors of type of annotation
3340  for (int i = 0; i < ancNCnt; i++) { // for each ancestor element
3341  Element ancEl = (Element) ancNodes.item(i);
3342  String ancTypeUri = ancEl.getAttribute("uri");
3343  AnnotType ancType = null;
3344 
3345  // query database for type of ancestor (type of annotation)
3346  params[0] = "uri";
3347  params[1] = ancTypeUri;
3348  List tList = pm.queryDB("AnnotType.findByUri", params);
3349  if (tList != null && !tList.isEmpty()) { // if type was found
3350  ancType = (AnnotType) tList.get(0);
3351  newAncestors.add(ancType); // add ancestor to the list of ancestors
3352  } else { // if type was not found
3353  // it possibly can be new type
3354  Iterator<AnnotType> ancIter = (Iterator<AnnotType>) requestInfo.getFlier().getAddedTypes().iterator();
3355  while (ancIter.hasNext() && ancestorType == null) { // look over just added types
3356  AnnotType addedT = ancIter.next();
3357  if (addedT.getUri().equals(ancTypeUri)) { // if type was found
3358  ancType = addedT;
3359  }
3360  }
3361  if (ancType == null) { // if ancestor is not new type
3362  errInfo = errInfo.concat("<ancestor uri=\"" + ancTypeUri + "\"/>");
3363  ancErrCnt++; // increase error count and skip ancestor
3365  String msg = "Unknown ancestor in the list of ancestors of the type of annotation: "
3366  + ancTypeUri;
3367  Logger.getLogger(MessageProcessor.class.getName()).log(Level.ALL, msg);
3368  }
3369  } else { // if ancestor is new type
3370  newAncestors.add(ancType); // add ancestor to the list of ancestors
3371  }
3372  } // if type was not found
3373  } // for each ancestor element
3374 
3375  // add primary ancestor
3376  if (!newAncestors.contains(ancestorType) && ancestorType != null) {
3377  newAncestors.add(ancestorType);
3378  }
3379  // if primary ancestor is not set, set it
3380  if (!newAncestors.isEmpty() && ancestorType == null) {
3381  ancestorType = newAncestors.get(0);
3382  retType.setAncestorType(ancestorType);
3383  }
3384 
3385  if (update) { // if it's update of type of annotation
3386  if (errCnt > 0 || ancErrCnt > 0) { // if errors occurred and some attributes or ancestors was discarded
3387  errInfo = errInfo.concat("</type>"); // completes informations about type
3388  // create error message
3389  int langNum = requestInfo.getSession().getLanguageNum();
3390  int lod = requestInfo.getSession().getProtocolLOD();
3391  requestInfo.addError(lod, langNum, Localisation.ERROR_18_BAD_EDITED_TYPE, errInfo);
3392  return null; // type of annotation can't be updated
3393  } else { // if errors does not occurred
3394  // (modified attributes are saved only if error count is 0)
3395  retType.setAttributes(newAttrs); // save new attributes to object with type
3396  retType.setAncestorTypes(newAncestors); // save new ancestors to object with type
3397  retType.setId(qType.getId()); // set id of type to id of updated (replaced) type
3398  }
3399  } else { // if it's new type of annotation
3400  if (errCnt > 0 || ancErrCnt > 0) { // if errors occurred
3401  errInfo = errInfo.concat("</type>"); // completes informations about type
3402  }
3403  if (errCnt > 0) { // if errors occurred and some attributes was discarded
3404  // create error message
3405  int langNum = requestInfo.getSession().getLanguageNum();
3406  int lod = requestInfo.getSession().getProtocolLOD();
3407  requestInfo.addError(lod, langNum, Localisation.ERROR_17_TYPE_ATTRIBUTES_MALFORMED, errInfo);
3408  }
3409  if (ancErrCnt > 0) { // if errors occurred and some ancestors was discarded
3410  // create error message
3411  int langNum = requestInfo.getSession().getLanguageNum();
3412  int lod = requestInfo.getSession().getProtocolLOD();
3413  requestInfo.addError(lod, langNum, Localisation.ERROR_55_TYPE_ANCESTORS_MALFORMED, errInfo);
3414  }
3415  // Attributes of new type are partially or fully saved to type
3416  retType.setAttributes(newAttrs);
3417  // Ancestors of new type are partially or fully saved to type
3418  retType.setAncestorTypes(newAncestors);
3419  }
3420 
3421  return retType;
3422  } // processTypeEl()
3423 } // public class P1Processor
static void processTextModificationMsg(NodeList tmMsg, RequestInfo requestInfo)
static void processJoin(NodeList joinMsgs, RequestInfo requestInfo)
static void processSuggestions(NodeList suggestMsg, RequestInfo requestInfo)
Persistence manager (database manipulator)
Definition: PersistM.java:35
Class representing attribute of type of annotation.
static void processRefSuggestions(Element refSuggestEl, RequestInfo requestInfo)
static void logAttributeError(String errAnnotInfo, String name, String type, RequestInfo requestInfo, int errorCode, String message)
boolean containsSource(SubscribedSource source)
Abstract class representing more complex attribute.
static void breakdownType(AnnotType type, RequestInfo requestInfo)
Class representing annotated copy of document.
static Annotation processAddedAnnotEl(Element addedAnnotEl, RequestInfo requestInfo)
static BaseAttribute processAttributeEl(Element attributeEl, Annotation annot, RequestInfo requestInfo, int order, Integer cMethod)
static void processSynchronize(Element synchronizeEl, RequestInfo requestInfo)
Singleton for storing global variables.
Definition: AppBean.java:47
Class which process XML with messages in 4A protocol v 1.x.
static final boolean AUTO_SUBSCRIBE_OWN_GROUPS
Definition: Constants.java:89
static void processUnsubscribe(Element unsubscribeEl, EditorSession session, RequestInfo requestInfo)
static User processLogin(Element loginEl, RequestInfo requestInfo)
boolean containsUnsubscribedSource(SubscribedSource source)
static final ArrayList< String > SIMPLE_TYPES
Definition: Constants.java:153
Suggested annotation with informations about suggestion.
Static class which parses and process XML with messages.
Class representing user group.
Definition: UserGroup.java:47
static void processReload(NodeList reloadMsg, RequestInfo requestInfo)
Class representing parameter of user settings.
Definition: Settings.java:45
RequestInfo processXML(Element docEl, RequestInfo requestInfo)
Base class representing attribute of annotation.
Class representing type of annotation.
Definition: AnnotType.java:58
Class representing user.
Definition: User.java:51
Class representing modification of annotated document text.
static void processResynchronize(Element resynchronizeEl, RequestInfo requestInfo)
Flier with informations for comet handlers.
Definition: Flier.java:31
static AnnotType processTypeEl(Element typeEl, RequestInfo requestInfo, boolean update)
static Annotation processRemAnnotEl(Element remAnnotEl, RequestInfo requestInfo)
static void processAnnotations(Element annotationsEl, RequestInfo requestInfo)
ArrayList< SuggestionLogEntry > getConfirmedSuggestions()
Class attribute manager provides a way how to create new attributes.
Processed informations about client request.
static Fragment processFragmentEl(Element fragmentEl, Annotation annot, RequestInfo requestInfo)
static void processSettings(Element settingsEl, RequestInfo requestInfo)
static void processEntityRequest(Element entityReqEl, RequestInfo requestInfo)
static void processTypes(Element typesEl, RequestInfo requestInfo)
static Annotation processAnnotationDescEl(Element annotationEl, RequestInfo requestInfo, Annotation nestedIn, Integer cMethod)
Class responsible for localised strings.
static Annotation processEditedAnnotEl(Element updatedAnnotEl, RequestInfo requestInfo)
Informations about client session.
Utility class (manipulates RFC 3339 dates)
Definition: Util.java:29
ArrayList< AnnotType > getAddedTypes()
Definition: Flier.java:101
Class representing annotated fragment.
Definition: Fragment.java:48
Class representing attribute of type Person.
static void processLeave(NodeList leaveMsgs, RequestInfo requestInfo)
static void processSubscribe(Element subscribeEl, EditorSession session, RequestInfo requestInfo)