View Javadoc
1   package uk.ac.ebi.intenz.webapp.utilities;
2   
3   import java.io.IOException;
4   import java.net.HttpURLConnection;
5   import java.net.InetSocketAddress;
6   import java.net.Proxy;
7   import java.net.URL;
8   import java.net.URLConnection;
9   import java.util.HashSet;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Set;
13  
14  import javax.servlet.http.HttpServletRequest;
15  
16  import org.apache.commons.collections.list.SetUniqueList;
17  import org.apache.commons.validator.Field;
18  import org.apache.commons.validator.ValidatorAction;
19  import org.apache.commons.validator.util.ValidatorUtils;
20  import org.apache.struts.action.ActionMessage;
21  import org.apache.struts.action.ActionMessages;
22  
23  import uk.ac.ebi.biobabel.util.StringUtil;
24  import uk.ac.ebi.biobabel.validator.DbIdentifierValidator;
25  import uk.ac.ebi.biobabel.validator.SyntaxValidator;
26  import uk.ac.ebi.intenz.domain.constants.EnzymeViewConstant;
27  import uk.ac.ebi.intenz.domain.constants.XrefDatabaseConstant;
28  import uk.ac.ebi.intenz.domain.enzyme.EnzymeLink;
29  import uk.ac.ebi.intenz.domain.exceptions.DomainException;
30  import uk.ac.ebi.intenz.webapp.dtos.CofactorDTO;
31  import uk.ac.ebi.intenz.webapp.dtos.CommentDTO;
32  import uk.ac.ebi.intenz.webapp.dtos.EnzymeDTO;
33  import uk.ac.ebi.intenz.webapp.dtos.EnzymeLinkDTO;
34  import uk.ac.ebi.intenz.webapp.dtos.EnzymeNameDTO;
35  import uk.ac.ebi.intenz.webapp.dtos.ReactionDTO;
36  import uk.ac.ebi.intenz.webapp.dtos.ReferenceDTO;
37  
38  /**
39   * This class ...
40   *
41   * @author Michael Darsow
42   * @version $Revision: 1.3 $ $Date: 2008/03/12 12:29:16 $
43   */
44  public class IntEnzValidations {
45  
46    // -------------------------- STATIC METHODS --------------------------
47  
48  	private static String getStringValue(Object bean, Field field) {
49  		String value = null;
50  		if (isString(bean)) {
51  			value = (String) bean;
52  		} else {
53  			value = ValidatorUtils.getValueAsString(bean, field.getProperty());
54  		}
55  		return value;
56  	}
57  
58    /**
59     * Validate EC numbers
60     */
61    public static boolean validateEc(Object bean,
62            ValidatorAction validatorAction,
63            Field field,
64            ActionMessages actionMessages,
65            HttpServletRequest httpServletRequest) {
66        String value = getStringValue(bean, field);
67        if (value == null) {
68            actionMessages.add(field.getKey(), new ActionMessage("The given EC is invalid."));
69            return false;
70        }
71  
72        return DbIdentifierValidator.getInstance().validate(value,
73                DbIdentifierValidator.EC_NUMBER);
74    }
75  
76    public static boolean validateBrackets(Object bean,
77            ValidatorAction validatorAction,
78            Field field,
79            ActionMessages actionMessages,
80            HttpServletRequest httpServletRequest){
81  	  String value = getStringValue(bean, field);
82  	  return SyntaxValidator.getInstance().validate(value, SyntaxValidator.BRACKETS);
83    }
84  
85    /**
86     * Validate one CAS registry number
87     */
88    public static boolean validateCASRegistryNumberFormat(EnzymeLinkDTO CASLink) {
89      if (CASLink == null) throw new NullPointerException("Parameter 'CASLink' must not be null.");
90      return DbIdentifierValidator.getInstance().validate(CASLink.getAccession(),
91              DbIdentifierValidator.CAS_REGISTRY_NUMBER);
92    }
93  
94    public static boolean validateCASRegistryNumber(Object bean,
95            ValidatorAction validatorAction,
96            Field field,
97            ActionMessages actionMessages,
98            HttpServletRequest httpServletRequest) {
99        List casLinks = null;
100       if (bean instanceof List){
101           casLinks = (List) bean;
102       } else {
103           casLinks = ((EnzymeDTO) bean).getCasLinks();
104       }
105       for (int i = 0; i < casLinks.size(); i++){
106           EnzymeLinkDTO link = (EnzymeLinkDTO) casLinks.get(i);
107           if (!DbIdentifierValidator.getInstance().validate(link.getAccession(),
108                   DbIdentifierValidator.CAS_REGISTRY_NUMBER)) return false;
109       }
110       return true;
111   }
112 
113 
114 //  public static boolean validateXChars(Object bean,
115 //                                       ValidatorAction validatorAction,
116 //                                       Field field,
117 //                                       ActionMessages actionMessages,
118 //                                       HttpServletRequest httpServletRequest) {
119 //    String value = null;
120 //    if (isString(bean))
121 //      value = (String) bean;
122 //    else
123 //      value = ValidatorUtils.getValueAsString(bean, field.getProperty());
124 //
125 //    // If nothing's there then checking is not necessary.
126 //    if (value == null) return true;
127 //
128 //    return true;
129 //  }
130 
131   /**
132    * This method is used by Action classes to check the content of an enzyme form before performing the actual command.
133    *
134    * @param enzymeDTO DTO storing the form values.
135    * @param errors    List for storing error errors.
136    */
137   public static void validateEnzymeDTOLists(EnzymeDTO enzymeDTO, ActionMessages errors) {
138     if (enzymeDTO == null) throw new NullPointerException("Parameter 'enzymeDTO' must not be null.");
139     if (errors == null) throw new NullPointerException("Parameter 'errors' must not be null.");
140     validateCommonNames(enzymeDTO.getCommonNames(), errors);
141     validateSynonyms(enzymeDTO.getSynonyms(), errors);
142     validateReactions(enzymeDTO.getReactionDtos(), errors);
143 //    validateCofactors(enzymeDTO.getCofactors(), errors);
144     validateComments(enzymeDTO.getComments(), errors);
145     validateLinks(enzymeDTO.getLinks(), enzymeDTO.getEc(), errors);
146     //validateReferences(enzymeDTO.getReferences(), null, null, errors, null);
147   }
148 
149   protected static boolean isString(Object o) {
150     return (o == null) ? true : String.class.isInstance(o);
151   }
152 
153   // ---------------- PRIVATE METHODS ----------------------------------------------
154 
155   /**
156    * Checks the value of the common name's view.
157    * <p/>
158    * It is not valid to have two common names with the view value 'INTENZ'.
159    *
160    * @param commonNames Common names list to be checked.
161    * @param errors      List for storing error errors.
162    */
163   private static void validateCommonNames(List commonNames, ActionMessages errors) {
164     assert commonNames != null : "Parameter 'commonNames' must not be null.";
165     assert errors != null : "Parameter 'errors' must not be null.";
166 
167     removeEmptyNameItems(commonNames);
168     removeDuplicates(commonNames);
169     boolean intenzViewUsed = false;
170     for (int iii = 0; iii < commonNames.size(); iii++) {
171       EnzymeNameDTO enzymeNameDTO = (EnzymeNameDTO) commonNames.get(iii);
172       if (EnzymeViewConstant.isInIntEnzView(enzymeNameDTO.getView()) &&
173           ((enzymeNameDTO.getName() != null && !enzymeNameDTO.getName().equals("")) ||
174            (enzymeNameDTO.getXmlName() != null && !enzymeNameDTO.getXmlName().equals("")))) {
175         if (intenzViewUsed) {
176           ActionMessage message = new ActionMessage("errors.form.common_name.invalidView");
177           errors.add("commonName", message);
178         } else
179           intenzViewUsed = true;
180       }
181     }
182   }
183 
184   private static void removeEmptyNameItems(List names) {
185     assert names != null : "Parameter 'names' must not be null.";
186     for (int iii = 0; iii < names.size(); iii++) {
187       EnzymeNameDTO enzymeNameDTO = (EnzymeNameDTO) names.get(iii);
188       if (enzymeNameDTO.getXmlName() == null || enzymeNameDTO.getXmlName().equals("")) {
189         names.remove(iii);
190         iii--;
191       }
192     }
193   }
194 
195   private static void removeDuplicates(List list) {
196     list.retainAll(SetUniqueList.decorate(list));
197   }
198 
199   /**
200    * At the moment this method only removes empty and duplicated items from the list of synonyms.
201    *
202    * @param synonyms List of synonyms to be checked.
203    * @param errors   List for storing error errors.
204    */
205   private static void validateSynonyms(List synonyms, ActionMessages errors) {
206     assert synonyms != null : "Parameter 'synonyms' must not be null.";
207     assert errors != null : "Parameter 'errors' must not be null.";
208     removeEmptyNameItems(synonyms);
209     removeDuplicates(synonyms);
210   }
211 
212   /**
213    * Checks if at least one reaction exists.
214    * <p/>
215    * Otherwise the user will be informed that one or more reactions have to exist for an enzyme entry.
216    *
217    * @param reactions List of reactions.
218    * @param errors    List for storing error errors.
219    */
220   private static void validateReactions(List reactions, ActionMessages errors) {
221     assert reactions != null : "Parameter 'reactions' must not be null.";
222     assert errors != null : "Parameter 'errors' must not be null.";
223     removeEmptyReactionItems(reactions);
224     removeDuplicates(reactions);
225     if (reactions.size() == 0) {
226       ActionMessage message = new ActionMessage("errors.form.reaction.notExisting");
227       errors.add("reaction", message);
228     }
229   }
230 
231   private static void removeEmptyReactionItems(List reactions) {
232     for (int iii = 0; iii < reactions.size(); iii++) {
233       ReactionDTO reactionDTO = (ReactionDTO) reactions.get(iii);
234       if (reactionDTO.getXmlTextualRepresentation() == null || reactionDTO.getXmlTextualRepresentation().equals("")) {
235         reactions.remove(iii);
236         iii--;
237       }
238     }
239   }
240 
241   /**
242    * At the moment this method only removes empty and duplicated items from the list of cofactors.
243    *
244    * @param cofactors The list of cofactors.
245    * @param errors    List for storing error errors.
246    * @deprecated will be using sets of cofactors (no emptiness, no duplicates)
247    */
248   private static void validateCofactors(List cofactors, ActionMessages errors) {
249     assert cofactors != null : "Parameter 'cofactors' must not be null.";
250     assert errors != null : "Parameter 'errors' must not be null.";
251     removeEmptyCofactorItems(cofactors);
252     removeDuplicates(cofactors);
253   }
254 
255   private static void removeEmptyCofactorItems(List cofactors) {
256     for (int iii = 0; iii < cofactors.size(); iii++) {
257       CofactorDTO cofactorDTO = (CofactorDTO) cofactors.get(iii);
258       if (cofactorDTO.getXmlCofactorValue() == null || cofactorDTO.getXmlCofactorValue().equals("")) {
259         cofactors.remove(iii);
260         iii--;
261       }
262     }
263   }
264 
265   /**
266    * At the moment this method only removes empty and duplicated items from the list of comments.
267    *
268    * @param comments The list of comments.
269    * @param errors   List for storing error errors.
270    */
271   private static void validateComments(List comments, ActionMessages errors) {
272     assert comments != null : "Parameter 'comments' must not be null.";
273     assert errors != null : "Parameter 'errors' must not be null.";
274     removeEmptyCommentItems(comments);
275     removeDuplicates(comments);
276     checkForPeriod(comments, errors);
277   }
278 
279   private static void removeEmptyCommentItems(List comments) {
280     for (int iii = 0; iii < comments.size(); iii++) {
281       CommentDTO commentDTO = (CommentDTO) comments.get(iii);
282       if (commentDTO.getXmlComment() == null || commentDTO.getXmlComment().equals("")) {
283         comments.remove(iii);
284         iii--;
285       }
286     }
287   }
288 
289   private static void checkForPeriod(List list, ActionMessages errors) {
290     for (int iii = 0; iii < list.size(); iii++) {
291       CommentDTO commentDTO = (CommentDTO) list.get(iii);
292       if (!commentDTO.getXmlComment().endsWith(".")) {
293         ActionMessage error = new ActionMessage("errors.form.comment.missing_period", "" + (iii + 1));
294         errors.add("comments", error);
295         return;
296       }
297     }
298   }
299 
300   /**
301    * Checks the list of links for valid values.
302    * <p/>
303    * The following links are being checked:
304    * <ul>
305    * <li>CAS (value must exist)</li>
306    * <li>MEROPS (valid hyperlink must exist)</li>
307    * <li>OMIM (values for name and MIM accession must exist)</li>
308    * <li>PROSITE (PROSITE accession must exist)</li>
309    * <li>DIAGRAM (a valid hyperlink and a value for the name must exist)</li>
310    * </ul>
311    *
312    * @param links  List of links.
313    * @param errors List for storing error errors.
314    */
315   private static void validateLinks(List links, String ec, ActionMessages errors) {
316     assert links != null : "Parameter 'links' must not be null.";
317     assert ec != null : "Parameter 'ec' must not be null.";
318     assert errors != null : "Parameter 'errors' must not be null.";
319     removeEmptyLinkItems(links);
320     removeLinkDuplicates(links);
321     try {
322       updateStaticLinks(links, ec);
323     } catch (DomainException e) {
324       ActionMessage message = new ActionMessage(e.getMessageKey(), e.getProperty());
325       errors.add("links", message);
326     }
327     for (int iii = 0; iii < links.size(); iii++) {
328       EnzymeLinkDTO enzymeLinkDTO = (EnzymeLinkDTO) links.get(iii);
329       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.CAS.getDisplayName())) {
330         if (enzymeLinkDTO.getAccession() == null || enzymeLinkDTO.getAccession().equals("")
331                 || !validateCASRegistryNumberFormat(enzymeLinkDTO)) {
332           ActionMessage message = new ActionMessage("errors.form.link.invalidCasValue");
333           errors.add("links", message);
334         }
335       }
336       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.MEROPS.getDisplayName())) {
337         try {
338           URL url = new URL(enzymeLinkDTO.getUrl());
339           URLConnection connection = url.openConnection();
340           connection.connect();
341         } catch (IOException e) {
342           ActionMessage message = new ActionMessage("errors.form.link.invalidMeropsUrl");
343           errors.add("links", message);
344         }
345       }
346       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.MIM.getDisplayName())) {
347         if (enzymeLinkDTO.getAccession() == null || enzymeLinkDTO.getAccession().equals("") ||
348             enzymeLinkDTO.getName() == null || enzymeLinkDTO.getName().equals("")) {
349           ActionMessage message = new ActionMessage("errors.form.link.MimIncomplete");
350           errors.add("links", message);
351         }
352       }
353       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.PROSITE.getDisplayName())) {
354         if (enzymeLinkDTO.getAccession() == null || enzymeLinkDTO.getAccession().equals("")) {
355           ActionMessage message = new ActionMessage("errors.form.link.invalidPrositeValue");
356           errors.add("links", message);
357         }
358       }
359       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.DIAGRAM.getDisplayName())) {
360         if (enzymeLinkDTO.getName() == null || enzymeLinkDTO.getName().equals("")) {
361           ActionMessage message = new ActionMessage("errors.form.link.invalidDiagramName");
362           errors.add("links", message);
363         }
364         try {
365           URL url = new URL(enzymeLinkDTO.getUrl());
366           // Set up proxy TODO: TAKE THIS OUT OF HERE
367           Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("www-proxy.ebi.ac.uk", 8080));
368           HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
369           if (connection.getResponseCode() != HttpURLConnection.HTTP_OK){
370               ActionMessage message = new ActionMessage("errors.form.link.invalidDiagramUrl");
371               errors.add("links", message);        	  
372           }
373         } catch (IOException e) {
374           ActionMessage message = new ActionMessage("errors.form.link.invalidDiagramUrl");
375           errors.add("links", message);
376         }
377       }
378     }
379   }
380 
381   /**
382    * All database links which name value is <code>NONE</code> will be removed.
383    * <p/>
384    * All the others will be kept and checked in the updating Action.
385    *
386    * @param links The list of links to be checked.
387    */
388   private static void removeEmptyLinkItems(List links) {
389     assert links != null : "Parameter 'links' must not be null.";
390     for (int iii = 0; iii < links.size(); iii++) {
391       EnzymeLinkDTO enzymeLinkDTO = (EnzymeLinkDTO) links.get(iii);
392       if (enzymeLinkDTO.getDatabaseName().equals(XrefDatabaseConstant.UNDEF.getDisplayName())) {
393         links.remove(iii);
394         iii--;
395       }
396     }
397   }
398 
399   /**
400    * Removes duplicates from the list of links.
401    *
402    * @param links The list of links to be checked.
403    */
404   private static void removeLinkDuplicates(List links) {
405     assert links != null : "Parameter 'links' must not be null.";
406     Set databaseNames = new HashSet();
407     Set checkedLinks = new HashSet();
408     for (int iii = 0; iii < links.size(); iii++) {
409       EnzymeLinkDTO enzymeLinkDTO = (EnzymeLinkDTO) links.get(iii);
410       if (databaseNames.contains(enzymeLinkDTO.getDatabaseName())) {
411         // If the given name is a valid xref name and it is a unique xref then remove it from the list.
412         if (XrefDatabaseConstant.isUniqueXrefDatabaseName(enzymeLinkDTO.getDatabaseName())) {
413           links.remove(enzymeLinkDTO);
414         } else { // Remove xref only if all xref values are the same.
415           for (Iterator it = checkedLinks.iterator(); it.hasNext();) {
416             EnzymeLinkDTO checkedLink = (EnzymeLinkDTO) it.next();
417             if (checkedLink.equals(enzymeLinkDTO)) links.remove(enzymeLinkDTO);
418           }
419         }
420       } else {
421         databaseNames.add(enzymeLinkDTO.getDatabaseName());
422         checkedLinks.add(enzymeLinkDTO);
423       }
424     }
425   }
426 
427   private static void updateStaticLinks(List links, String ec) throws DomainException {
428     assert links != null : "Parameter 'links' must not be null.";
429     for (int iii = 0; iii < links.size(); iii++) {
430       EnzymeLinkDTO enzymeLinkDTO = (EnzymeLinkDTO) links.get(iii);
431       EnzymeLink staticLink = EnzymeLink.getStaticLink(XrefDatabaseConstant.valueOf(enzymeLinkDTO.getDatabaseCode()));
432       if (staticLink != null) {
433         enzymeLinkDTO.setDatabaseName(staticLink.getXrefDatabaseConstant().getDisplayName());
434         enzymeLinkDTO.setName(staticLink.getName());
435         enzymeLinkDTO.setUrl(staticLink.getFullUrl(ec));
436       }
437     }
438   }
439 
440   public static boolean validateReferences(Object obj,
441           ValidatorAction validatorAction,
442           Field field,
443           ActionMessages actionMessages,
444           HttpServletRequest httpServletRequest) {
445     assert obj != null : "Parameter 'references' must not be null.";
446     List<ReferenceDTO> references = ((EnzymeDTO) obj).getReferences();
447     removeEmptyReferenceItems(references);
448     removeDuplicates(references);
449       for (ReferenceDTO referenceDTO : references) {
450         if (StringUtil.isNullOrEmpty(referenceDTO.getYear())) return false;
451       }
452     return true;
453   }
454 
455   private static void removeEmptyReferenceItems(List references) {
456     assert references != null : "Parameter 'references' must not be null.";
457     for (int iii = 0; iii < references.size(); iii++) {
458       ReferenceDTO referenceDTO = (ReferenceDTO) references.get(iii);
459       if (referenceDTO.isEmpty()) {
460         references.remove(iii);
461         iii--;
462       }
463     }
464   }
465 
466   public static boolean hasNoUnicode(String s){
467 	  for (int i = 0; i < s.length(); i++) {
468 		  int codePoint = s.codePointAt(i);
469 		  if (codePoint > 127) return false;
470 	  }
471 	  return true;
472   }
473 
474 }
475