/*
* Copyright (C) Lennart Martens
*
* Contact: lennart.martens AT UGent.be (' AT ' to be replaced with '@')
*/
package com.compomics.util.general.servlet;
import org.apache.log4j.Logger;
import java.io.*;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.StringTokenizer;
import javax.servlet.http.*;
import com.compomics.util.general.MassCalc;
import com.compomics.util.general.UnknownElementMassException;
/*
* CVS information:
*
* $Revision: 1.3 $
* $Date: 2007/07/06 09:41:54 $
*/
/**
* This class implements the MassCalc class as a servlet. <br>
* It also generates its own submission form upon <i>first contact</i>.
*
* @see com.compomics.util.general.MassCalc
* @author Lennart Martens
*/
public class MassCalcServlet extends HttpServlet {
// Class specific log4j logger for MassCalcServlet instances.
Logger logger = Logger.getLogger(MassCalcServlet.class);
private static final String SEQUENCE = "SEQUENCE";
private static final String MASSLISTCHOICE = "MASSLISTCHOICE";
private static final String MONOBIOCHEM = "MONOBIOCHEM";
private static final String MONOAA = "MONOAA";
private static final String SELFLIST = "SELFLIST";
private static final String ADDSELFLISTBIOCHEM = "ADDSELFLISTBIOCHEM";
private static final String ADDSELFLISTAA = "ADDSELFLISTAA";
private static final String SELFDEFINEDLIST = "SELFDEFINEDLIST";
private static final int NO_ERROR = 0;
private static final int NO_SEQUENCE = 1;
private static final int NO_SELFDEFINEDLIST = 2;
private static final int WRONG_SELFDEFINEDLIST = 3;
private static final int ONLY_SELF = 1;
private static final int ADD_SELF = 2;
/**
* Override of parent class, implemented here as a simple forward to the
* 'doPost' method.
*
* @param req HttpServletRequest with the request
* @param res HttpServletResponse with the response
*/
public void doGet(HttpServletRequest req, HttpServletResponse res) {
this.doPost(req, res);
}
/**
* Override of parent class; this method handles post requests, and through
* forwarding also get requests. The function of this servlet is to read a
* sequence from the request object, and write the resulting mass
* to the response object.
*
* @param req HttpServletRequest with the request
* @param res HttpServletResponse with the response
*/
public void doPost(HttpServletRequest req, HttpServletResponse res) {
try {
// First we see whether a parameter is present.
// If this is the case, we should generate the submission form.
if (req.getParameterNames().hasMoreElements()) {
// Okay, we've got parameters, see if they're correct.
Enumeration en = req.getParameterNames();
HashMap params = new HashMap(3);
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
params.put(key, req.getParameter(key));
}
// For the self-defined list.
int selfDefined = 0;
HashMap selfList = null;
// Checking for a sequence...
if (params.get(SEQUENCE) == null || ((String) params.get(SEQUENCE)).trim().equals("")) {
// Re-generate form with error message.
this.generateSubmissionForm(res, NO_SEQUENCE);
return;
} else if (params.get(MASSLISTCHOICE).equals(SELFLIST)) {
// Flag that we've got a self defined list to use exclusively.
selfDefined = ONLY_SELF;
// See if there is a list, and see if it can be parsed.
if ((params.get(SELFDEFINEDLIST) == null) || (((String) params.get(SELFDEFINEDLIST)).trim().equals(""))) {
// Re-generate form with error message.
this.generateSubmissionForm(res, NO_SELFDEFINEDLIST);
return;
} else {
// There is a list, see if we can parse it.
String list = (String) params.get(SELFDEFINEDLIST);
try {
selfList = this.parseSelfList(list);
} catch (Exception e) {
this.generateSubmissionForm(res, WRONG_SELFDEFINEDLIST);
}
}
} else if (params.get(MASSLISTCHOICE).equals(ADDSELFLISTBIOCHEM)
|| params.get(MASSLISTCHOICE).equals(ADDSELFLISTAA)) {
// Flag that we've got a self defined list to use
// additively.
selfDefined = ADD_SELF;
// There can be a list, see if we can parse it.
String list = (String) params.get(SELFDEFINEDLIST);
try {
selfList = this.parseSelfList(list);
} catch (Exception e) {
this.generateSubmissionForm(res, WRONG_SELFDEFINEDLIST);
}
}
// Okay, in getting here, we should be able to compute!
String sequence = (String) params.get(SEQUENCE);
int massList = 0;
if (selfDefined == ONLY_SELF) {
massList = -1;
} else {
String mlChoice = (String) params.get(MASSLISTCHOICE);
mlChoice = mlChoice.trim();
if (mlChoice.equals(MONOBIOCHEM) || mlChoice.equals(ADDSELFLISTBIOCHEM)) {
massList = MassCalc.MONOELEMENTS;
} else if (mlChoice.equals(MONOAA) || mlChoice.equals(ADDSELFLISTAA)) {
massList = MassCalc.MONOAA;
}
}
double mass = 0.0;
MassCalc mc = null;
// Bigger than zero: use built-in list,
// but possibly additively use self-defined list.
// Else: use only self-defined list.
if (massList >= 0) {
if (selfDefined == ADD_SELF) {
// Additive selflist.
mc = new MassCalc(massList, selfList);
} else {
// Plain old built-in type.
mc = new MassCalc(massList);
}
} else {
// Use only self defined list.
mc = new MassCalc(selfList);
}
try {
mass = mc.calculateMass(sequence);
this.writeOutput(res, sequence, mass);
} catch (UnknownElementMassException uem) {
this.handleError(res, sequence, uem);
}
} else {
// No parameters found. So generate the form.
this.generateSubmissionForm(res, NO_ERROR);
}
} catch (IOException ioe) {
}
}
/**
* THis method generates the submission form that users will employ to enter the
* sequence for which they want to obtain a mass.
*
* @param res HttpServletResponse with the servlet response object
* @param error int with the error status
* @throws IOException if the form could not be written to stream
*/
private void generateSubmissionForm(HttpServletResponse res, int error) throws IOException {
PrintWriter out = res.getWriter();
out.println("<html>");
out.println(" <head><title>Generic Mass Calculator (L. Martens)</title></head>");
out.println(" <body>");
out.println(" <h1>Generic mass calculator <i>(by Lennart Martens)</i></h1>");
// Check for error mesages to be displayed.
if (error != NO_ERROR) {
this.printErrorMessage(out, error);
}
out.println(" <br /><hr /><br />");
out.println(" <form method=\"POST\" action=\"http://beo04.rug.ac.be/utilities/masscalc\">");
out.println(" <table>");
out.println(" <tr>");
out.println(" <td align=\"center\">");
out.println(" <h3>Paste your sequence here:</h3>");
out.println(" </td>");
out.println(" <td>");
out.println(" <h3>Paste your own masslist here (key=value)</h3>");
out.println(" </td>");
out.println(" </tr>");
out.println(" <tr>");
out.println(" <td align=\"center\" valign=\"top\">");
out.println(" <textarea name=\"" + SEQUENCE + "\" rows=\"6\" cols=\"40\"></textarea>");
out.println(" </td>");
out.println(" <td align=\"center\" valign=\"top\" rowspan=\"2\">");
out.println(" <textarea name=\"" + SELFDEFINEDLIST + "\" rows=\"12\" cols=\"30\"></textarea>");
out.println(" </td>");
out.println(" </tr>");
out.println(" <tr>");
out.println(" <td>");
out.println(" <br />");
out.println(" <input type=\"radio\" name=\"" + MASSLISTCHOICE + "\" value=\"" + MONOBIOCHEM + "\" checked/> <b>Monoisotopic biochemical elements</b>");
out.println(" <br />");
out.println(" <input type=\"radio\" name=\"" + MASSLISTCHOICE + "\" value=\"" + MONOAA + "\" /> <b>Monoisotopic amino acids</b>");
out.println(" <br />");
out.println(" <input type=\"radio\" name=\"" + MASSLISTCHOICE + "\" value=\"" + SELFLIST + "\" /> <b>Self-defined list</b>");
out.println(" <br />");
out.println(" <input type=\"radio\" name=\"" + MASSLISTCHOICE + "\" value=\"" + ADDSELFLISTBIOCHEM + "\" /> <b>Add/override self-defined elements to biochem list</b>");
out.println(" <br />");
out.println(" <input type=\"radio\" name=\"" + MASSLISTCHOICE + "\" value=\"" + ADDSELFLISTAA + "\" /> <b>Add/override self-defined elements to AA list</b>");
out.println(" <br />");
out.println(" </td>");
out.println(" </tr>");
out.println(" </table>");
out.println(" <br /><br /><br /><br />");
out.println(" <input type=\"submit\" value=\"Calculate!\" />");
out.println(" <br />");
out.println(" <input type=\"reset\" value=\"Reset form.\" />");
out.println(" </form>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
/**
* Prints the error message.
*
* @param out
* @param aErrorCode
*/
private void printErrorMessage(PrintWriter out, int aErrorCode) {
switch (aErrorCode) {
case NO_ERROR:
break;
case NO_SEQUENCE:
out.println(" <font color=\"red\"><h1>You need to enter a sequence!</h1></font>");
break;
case NO_SELFDEFINEDLIST:
out.println(" <font color=\"red\"><h1>If you select the 'Self defined list' choice, you need to specify a list in the text area on the right!</h1></font>");
out.println(" <br /><br />");
break;
case WRONG_SELFDEFINEDLIST:
out.println(" <font color=\"red\"><h1>Your self-defined list cannot be parsed! It should be formatted in KEY=VALUE pairs, KEY being a symbol of maximum two characters, the first character must be uppercase, the (optional) second character lowercase, and VALUE should hold a number. Only one KEY=VALUE pair per line!!!</h1></font>");
out.println(" <br /><br />");
break;
}
}
/**
* This method generates the HTML output for the calculated mass.
*
* @param aRes HttpServletResponse to write the output to
* @param aSequence String with the original query sequence
* @param aMass double with the calculated mass
* @throws IOException if the output could not be written to stream
*/
private void writeOutput(HttpServletResponse aRes, String aSequence, double aMass) throws IOException {
PrintWriter out = aRes.getWriter();
out.println("<html>");
out.println(" <head><title>Mass for " + aSequence + "</title></head>");
out.println(" <body>");
out.println(" <h1>Mass calculation results</h1>");
out.println(" <hr /><br /><br /><br />");
out.println(" <h3>Mass was: <font color=\"blue\">" + aMass + "</font> Da.</h3>");
out.println(" <br /><br />");
out.println(" <h4>Sequence was:<h4>");
out.println(" <font color=\"green\">" + aSequence + "</font>");
out.println(" </body>");
out.println("</html>");
out.flush();
out.close();
}
/**
* This method writes the HTML code to show the user when an error has occurred.
*
* @param aRes HttpServletResponse to write the output to
* @param aSequence String with the original query sequence
* @param aUem UnknownElementMassException thrown when a residue with unknown mass was entered
* @throws IOException if the output could not be written to stream
*/
private void handleError(HttpServletResponse aRes, String aSequence, UnknownElementMassException aUem) throws IOException {
PrintWriter out = aRes.getWriter();
out.println("<html>");
out.println(" <head><title>Unknown element '" + aUem.getElement() + "' encountered!</title></head>");
out.println(" <body>");
out.println(" <font color=\"red\"><h1>Unknown element '" + aUem.getElement() + "' encountered!</h1></font>");
out.println(" Did you type the case correctly according to IUPAC standards? <br />");
out.println(" Did you type amino acid one letter code and in UPPERCASE?");
out.println(" <br /><br /><hr /><br /><br />");
aUem.printStackTrace(out);
out.println(" </body>");
out.println("</html>");
out.flush();
out.close();
}
/**
* This method attempts to parse a String into a HashMap.
*
* @param aList String with the list to be parsed.
* @return HashMap if all goes well!
* @exception Exception if anything at all goes wrong!
*/
private HashMap parseSelfList(String aList) throws Exception {
HashMap toReturn = new HashMap();
aList = aList.trim();
StringTokenizer st = new StringTokenizer(aList, " =_:\n");
while (st.hasMoreTokens()) {
String key = st.nextToken();
Double value = new Double(st.nextToken());
toReturn.put(key, value);
}
return toReturn;
}
}