servlets.Analysis_servlets.java Source code

Java tutorial

Introduction

Here is the source code for servlets.Analysis_servlets.java

Source

/* ***************************************************************
 *  This file is part of STATegra EMS.
 *
 *  STATegra EMS is free software: you can redistribute it and/or 
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation, either version 3 of 
 *  the License, or (at your option) any later version.
 * 
 *  STATegra EMS is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with STATegra EMS.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  More info http://bioinfo.cipf.es/stategraems
 *  Technical contact stategraemsdev@gmail.com
 *  *************************************************************** */
package servlets;

import bdManager.DAO.DAO;
import bdManager.DAO.DAOProvider;
import bdManager.DAO.analysis.Analysis_JDBCDAO;
import bdManager.DAO.analysis.Step_JDBCDAO;
import classes.Experiment;
import classes.Message;
import classes.User;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import common.ServerErrorManager;
import java.util.ArrayList;
import classes.analysis.Analysis;
import classes.analysis.NonProcessedData;
import classes.analysis.ProcessedData;
import classes.analysis.Step;
import classes.analysis.non_processed_data.IntermediateData;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import common.BlockedElementsManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.AccessControlException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.Cookie;
import org.apache.commons.codec.binary.Base64;

/**
 *
 * SERVLET FOR ANALYSIS:
 * +----------------------+-----------------------+---------------+------------------------------------------------------+---------------------+
 * | Resource             |       POST            |    GET        |                       PUT                            |        DELETE       |
 * +----------------------+-----------------------+---------------+------------------------------------------------------+---------------------+
 * | /rest/analysis       | Create a new analysis | List analysis | Replace analysis list with new analysis(Bulk update) | Delete all analysis |
 * +----------------------+-----------------------+---------------+------------------------------------------------------+---------------------+
 * | /rest/analysis/1234  |       Error           | Show analysis |       If exist update analysis else ERROR            | Delete analysis     |
 * +----------------------+-----------------------+---------------+------------------------------------------------------+---------------------+
 * | /rest/analysis/import| Import a new analysis |     Error     |                        Error                         |          Error      |
 * +----------------------+-----------------------+---------------+------------------------------------------------------+---------------------+
 *
 */
public class Analysis_servlets extends Servlet {

    String IMAGE_FILES_LOCATION = File.separator + "<experiment_id>" + File.separator + "analysis_images"
            + File.separator;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json");

        //OLD SERVICES
        if (!matchService(request.getServletPath(), "/rest/analysis(.*)")) {
            if (request.getServletPath().equals("/get_all_analysis")) {
                get_all_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/get_analysis")) {
                get_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/get_all_region_steps")) {
                //            get_all_region_steps_handler(request, response);
            } else if (request.getServletPath().equals("/add_analysis")) {
                add_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/update_analysis")) {
                update_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/lock_analysis")) {
                lock_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/unlock_analysis")) {
                unlock_analysis_handler(request, response);
            } else if (request.getServletPath().equals("/remove_analysis")) {
                delete_analysis_handler(request, response);
            }
            return;
        }

        //NEW SERVICES
        if (matchService(request.getPathInfo(), "/import")) {
            import_analysis_handler(request, response);
        } else if (matchService(request.getPathInfo(), "/(.+)")) {
            //Do nothing
        } else {
            add_analysis_handler(request, response);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");
        //OLD SERVICES
        if (!matchService(request.getServletPath(), "/rest/analysis(.*)")) {
            if (request.getServletPath().equals("/get_analysis_img_prev")) {
                getAnalysisPreviewImageHandler(request, response);
            } else if (request.getServletPath().equals("/get_analysis_img")) {
                getAnalysisImageHandler(request, response);
            } else if (request.getServletPath().equals("/get_step_subtypes")) {
                get_step_subtypes_handler(request, response);
            }
            return;
        }

        //NEW SERVICES
        if (matchService(request.getPathInfo(), "/export")) {
            export_analysis_handler(request, response);
        } else if (matchService(request.getPathInfo(), "/(.+)")) {
            get_analysis_handler(request, response);
        } else {
            get_all_analysis_handler(request, response);
        }
    }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json");
        if (matchService(request.getPathInfo(), "/(.+)")) {
            update_analysis_handler(request, response);
        } else {
            update_all_analysis_handler(request, response);
        }
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json");
        if (matchService(request.getPathInfo(), "/(.+)")) {
            delete_analysis_handler(request, response);
        } else {
            delete_all_analysis_handler(request, response);
        }
    }

    /*------------------------------------------------------------------------------------------*
     *                                                                                          *
     * POST REQUEST HANDLERS                                                                    *
     *                                                                                          *
     *------------------------------------------------------------------------------------------*/
    private void add_analysis_handler(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            String lockedID = null;
            boolean ROLLBACK_NEEDED = false;
            DAO daoInstance = null;
            Analysis analysis = null;
            try {
                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                String loggedUser = requestData.get("loggedUser").getAsString();
                String sessionToken = requestData.get("sessionToken").getAsString();

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 6b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                /**
                 * *******************************************************
                 * STEP 2 Get the new ID for the ANALYSIS. IF ERROR --> throws
                 * SQL Exception, GO TO STEP 5b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                daoInstance = DAOProvider.getDAOByName("Analysis");
                lockedID = daoInstance.getNextObjectID(null);

                /**
                 * *******************************************************
                 * STEP 3 Get the ANALYSIS Object by parsing the JSON data. IF
                 * ERROR --> throws JsonParseException, GO TO STEP 5b ELSE -->
                 * GO TO STEP 4
                 * *******************************************************
                 */
                //Get parameters
                analysis = Analysis.fromJSON(requestData.get("analysis_json_data"));

                ArrayList<Step> steps = new ArrayList<Step>();
                for (Step step : analysis.getNonProcessedData()) {
                    if (!"new_deleted".equals(step.getStatus())) {
                        steps.add(step);
                    }
                }
                analysis.setNonProcessedData(steps.toArray(new NonProcessedData[] {}));

                steps = new ArrayList<Step>();
                for (Step step : analysis.getProcessedData()) {
                    if (!"new_deleted".equals(step.getStatus())) {
                        steps.add(step);
                    }
                }
                analysis.setProcessedData(steps.toArray(new ProcessedData[] {}));

                String experimentID = requestData.get("currentExperimentID").getAsString();

                //Parse the data
                analysis.updateAnalysisID(lockedID);
                analysis.setAssociated_experiment(experimentID);

                /**
                 * *******************************************************
                 * STEP 4 Add the new ANALYSIS Object in the DATABASE. IF ERROR
                 * --> throws SQL Exception, GO TO STEP 5b ELSE --> GO TO STEP 5
                 * *******************************************************
                 */
                daoInstance.disableAutocommit();
                ROLLBACK_NEEDED = true;
                daoInstance.insert(analysis);

                /**
                 * *******************************************************
                 * STEP 5 COMMIT CHANGES TO DATABASE. throws SQLException IF
                 * ERROR --> throws SQL Exception, GO TO STEP 5b ELSE --> GO TO
                 * STEP 6
                 * *******************************************************
                 */
                daoInstance.doCommit();

            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "add_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 5b CATCH ERROR, CLEAN CHANGES. throws SQLException
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                    if (ROLLBACK_NEEDED) {
                        daoInstance.doRollback();
                    }
                } else {
                    JsonObject obj = new JsonObject();
                    obj.add("newID", new JsonPrimitive(lockedID));
                    response.getWriter().print(obj.toString());
                }

                /**
                 * UNLOCK THE IDS
                 */
                if (lockedID != null) {
                    BlockedElementsManager.getBlockedElementsManager().unlockID(lockedID);
                }
                /**
                 * *******************************************************
                 * STEP 6 Close connection.
                 * ********************************************************
                 */
                if (daoInstance != null) {
                    daoInstance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "add_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    private void import_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        try {
            String lockedID = null;
            boolean ROLLBACK_NEEDED = false;
            DAO daoInstance = null;
            Analysis analysis = null;
            try {

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 5b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                Map<String, Cookie> cookies = this.getCookies(request);
                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                String loggedUser, loggedUserID = null, sessionToken;
                if (cookies != null) {
                    loggedUser = cookies.get("loggedUser").getValue();
                    sessionToken = cookies.get("sessionToken").getValue();
                    loggedUserID = cookies.get("loggedUserID").getValue();
                } else {
                    String apicode = requestData.get("apicode").getAsString();
                    apicode = new String(Base64.decodeBase64(apicode));

                    loggedUser = apicode.split(":")[0];
                    sessionToken = apicode.split(":")[1];
                }

                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                if (loggedUserID == null) {
                    daoInstance = DAOProvider.getDAOByName("User");
                    loggedUserID = ((User) daoInstance.findByID(loggedUser, new Object[] { null, false, true }))
                            .getUserID();
                }

                String experimentID = requestData.get("experiment_id").getAsString();
                String origin = requestData.get("origin").getAsString();

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER EXISTS AND IF EXPERIMENT IS VALID
                 * *******************************************************
                 */
                daoInstance = DAOProvider.getDAOByName("Experiment");
                Experiment experiment = (Experiment) daoInstance.findByID(experimentID, null);
                if (experiment == null) {
                    throw new AccessControlException(experimentID + " is not a valid experiment identifier.");
                } else if (!experiment.isOwner(loggedUserID) && !experiment.isMember(loggedUserID)) {
                    throw new AccessControlException("User " + loggedUserID
                            + " is not a valid member of the experiment " + experimentID + ".");
                }

                /**
                 * *******************************************************
                 * STEP 2 Get the new ID for the ANALYSIS. IF ERROR --> throws
                 * SQL Exception, GO TO STEP 5b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                daoInstance = DAOProvider.getDAOByName("Analysis");
                lockedID = daoInstance.getNextObjectID(null);
                requestData.add("analysis_id", new JsonPrimitive(lockedID));

                /**
                 * *******************************************************
                 * STEP 3 Get the ANALYSIS Object by parsing the JSON data. IF
                 * ERROR --> throws JsonParseException, GO TO STEP 5b ELSE -->
                 * GO TO STEP 4
                 * *******************************************************
                 */
                analysis = Analysis.parseAnalysisData(origin, loggedUserID, requestData);
                analysis.updateAnalysisID(lockedID);
                analysis.setAssociated_experiment(experimentID);

                /**
                 * *******************************************************
                 * STEP 4 Add the new ANALYSIS Object in the DATABASE. IF ERROR
                 * --> throws SQL Exception, GO TO STEP 5b ELSE --> GO TO STEP 5
                 * *******************************************************
                 */
                daoInstance.disableAutocommit();
                ROLLBACK_NEEDED = true;
                daoInstance.insert(analysis);

                /**
                 * *******************************************************
                 * STEP 4 Add a new message. IF ERROR
                 * --> throws SQL Exception, GO TO STEP 5b ELSE --> GO TO STEP 5
                 * *******************************************************
                 */
                Message message = new Message();
                message.setUserID(loggedUserID);
                message.setType("info");
                message.setSender("STATegraEMS notifications");
                message.setTo(loggedUserID);
                message.setSubject("New analysis imported from " + origin);
                message.setContent("A new analysis called \"" + analysis.getAnalysisName()
                        + "\" has been created for experiment " + experimentID
                        + " using an external tool (data imported from " + origin + ").");

                daoInstance = DAOProvider.getDAOByName("Message");
                daoInstance.insert(message);

                /**
                 * *******************************************************
                 * STEP 5 COMMIT CHANGES TO DATABASE. throws SQLException IF
                 * ERROR --> throws SQL Exception, GO TO STEP 5b ELSE --> GO TO
                 * STEP 6
                 * *******************************************************
                 */
                daoInstance.doCommit();

            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "import_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 5b CATCH ERROR, CLEAN CHANGES. throws SQLException
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                    if (ROLLBACK_NEEDED) {
                        daoInstance.doRollback();
                    }
                } else {
                    JsonObject obj = new JsonObject();
                    obj.add("newID", new JsonPrimitive(lockedID));
                    response.getWriter().print(obj.toString());
                }

                /**
                 * UNLOCK THE IDS
                 */
                if (lockedID != null) {
                    BlockedElementsManager.getBlockedElementsManager().unlockID(lockedID);
                }
                /**
                 * *******************************************************
                 * STEP 6 Close connection.
                 * ********************************************************
                 */
                if (daoInstance != null) {
                    daoInstance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "import_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    /*------------------------------------------------------------------------------------------*
     *                                                                                          *
     * GET REQUEST HANDLERS                                                                     *
     *                                                                                          *
     *------------------------------------------------------------------------------------------*/
    private void get_all_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        try {
            DAO dao_instance = null;
            ArrayList<Object> analysisList = null;
            try {

                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                String loggedUser = requestData.get("loggedUser").getAsString();
                String sessionToken = requestData.get("sessionToken").getAsString();

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 5b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. Please sign in again.");
                }

                /**
                 * *******************************************************
                 * STEP 2 Get ALL THE ANALYSIS Object from DB. IF ERROR -->
                 * throws MySQL exception, GO TO STEP 3b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                boolean loadRecursive = false;
                if (requestData.has("loadRecursive")) {
                    loadRecursive = requestData.get("loadRecursive").getAsBoolean();
                }

                String experiment_id = null;
                if (requestData.has("experiment_id")) {
                    experiment_id = requestData.get("experiment_id").getAsString();
                } else {
                    experiment_id = requestData.get("currentExperimentID").getAsString();
                }

                Object[] params = { loadRecursive, experiment_id };
                dao_instance = DAOProvider.getDAOByName("Analysis");
                analysisList = dao_instance.findAll(params);
            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "get_all_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 3b CATCH ERROR. GO TO STEP 4
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                } else {
                    /**
                     * *******************************************************
                     * STEP 3A WRITE RESPONSE ERROR. GO TO STEP 4
                     * *******************************************************
                     */
                    String analysisJSON = "[";

                    for (int i = 0; i < analysisList.size(); i++) {
                        analysisJSON += ((Analysis) analysisList.get(i)).toJSON()
                                + ((i < analysisList.size() - 1) ? "," : "");
                    }
                    analysisJSON += "]";

                    response.getWriter().print(analysisJSON);
                }
                /**
                 * *******************************************************
                 * STEP 4 Close connection.
                 * ********************************************************
                 */
                if (dao_instance != null) {
                    dao_instance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "get_all_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    private void get_analysis_handler(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            DAO dao_instance = null;
            Analysis analysis = null;
            try {
                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                String loggedUser = requestData.get("loggedUser").getAsString();
                String sessionToken = requestData.get("sessionToken").getAsString();

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 5b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                /**
                 * *******************************************************
                 * STEP 2 Get THE ANALYSIS Object from DB. IF ERROR --> throws
                 * MySQL exception, GO TO STEP 3b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                dao_instance = DAOProvider.getDAOByName("Analysis");
                boolean loadRecursive = true;
                Object[] params = { loadRecursive };
                String analysis_id = requestData.get("analysis_id").getAsString();
                analysis = (Analysis) dao_instance.findByID(analysis_id, params);

            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "get_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 3b CATCH ERROR. GO TO STEP 4
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                } else {
                    /**
                     * *******************************************************
                     * STEP 3A WRITE SUCCESS RESPONSE. GO TO STEP 4
                     * *******************************************************
                     */
                    response.getWriter().print(analysis.toJSON());
                }
                /**
                 * *******************************************************
                 * STEP 4 Close connection.
                 * ********************************************************
                 */
                if (dao_instance != null) {
                    dao_instance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "get_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    private void export_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        try {
            DAO dao_instance = null;
            Analysis analysis = null;
            String tmpFile = "";
            Path tmpDir = null;

            try {
                String format = request.getParameter("format");
                if (format == null) {
                    format = "json";
                }

                Map<String, Cookie> cookies = this.getCookies(request);

                String loggedUser, sessionToken;
                loggedUser = cookies.get("loggedUser").getValue();
                sessionToken = cookies.get("sessionToken").getValue();

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 5b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                /**
                 * *******************************************************
                 * STEP 2 Get THE ANALYSIS Object from DB. IF ERROR --> throws
                 * MySQL exception, GO TO STEP 3b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                dao_instance = DAOProvider.getDAOByName("Analysis");
                boolean loadRecursive = true;
                Object[] params = { loadRecursive };
                String analysis_id = request.getParameter("analysis_id");
                analysis = (Analysis) dao_instance.findByID(analysis_id, params);

                tmpDir = Files.createTempDirectory(null);
                tmpFile = analysis.export(tmpDir.toString(), format,
                        this.getServletContext().getRealPath("/data/templates"));

            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "export_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 3b CATCH ERROR. GO TO STEP 4
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                } else {
                    /**
                     * *******************************************************
                     * STEP 3A WRITE RESPONSE ERROR. GO TO STEP 4
                     * *******************************************************
                     */
                    // reads input file from an absolute path
                    File downloadFile = new File(tmpFile);
                    try {
                        FileInputStream inStream = new FileInputStream(downloadFile);
                        // gets MIME type of the file
                        String mimeType = getServletContext().getMimeType(tmpFile);
                        if (mimeType == null) {
                            // set to binary type if MIME mapping not found
                            mimeType = "application/octet-stream";
                        }
                        response.setContentType(mimeType);
                        response.setHeader("Content-Disposition", "filename=\"" + downloadFile.getName() + "\"");

                        // obtains response's output stream
                        OutputStream outStream = response.getOutputStream();

                        byte[] buffer = new byte[4096];
                        int bytesRead = -1;

                        while ((bytesRead = inStream.read(buffer)) != -1) {
                            outStream.write(buffer, 0, bytesRead);
                        }

                        inStream.close();
                        outStream.close();
                    } catch (Exception ex) {
                    } finally {
                        if (downloadFile.exists()) {
                            downloadFile.delete();
                        }
                        if (tmpDir != null) {
                            Files.delete(tmpDir);
                        }
                    }
                }
                /**
                 * *******************************************************
                 * STEP 4 Close connection.
                 * ********************************************************
                 */
                if (dao_instance != null) {
                    dao_instance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "export_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    /*------------------------------------------------------------------------------------------*
     *                                                                                          *
     * PUT REQUEST HANDLERS                                                                     *
     *                                                                                          *
     *------------------------------------------------------------------------------------------*/
    private void update_all_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
    }

    private void update_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        try {
            ArrayList<String> BLOCKED_IDs = new ArrayList<String>();
            boolean ROLLBACK_NEEDED = false;
            DAO daoInstance1 = null;
            DAO daoInstance2 = null;

            try {

                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * 6b ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                Map<String, Cookie> cookies = this.getCookies(request);
                String loggedUser = cookies.get("loggedUser").getValue();
                String sessionToken = cookies.get("sessionToken").getValue();
                String loggedUserID = cookies.get("loggedUserID").getValue();

                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                /**
                 * *******************************************************
                 * STEP 3 Get the Object by parsing the JSON data. IF ERROR -->
                 * throws JsonParseException, GO TO STEP 6b ELSE --> GO TO STEP
                 * 4 *******************************************************
                 */
                Analysis analysis = Analysis.fromJSON(requestData.get("analysis_json_data"));

                daoInstance1 = DAOProvider.getDAOByName("Analysis");

                //CHECK IF CURRENT USER IS A VALID OWNER (AVOID HACKING)
                boolean loadRecursive = true;
                Analysis analysisAux = (Analysis) daoInstance1.findByID(analysis.getAnalysisID(),
                        new Object[] { loadRecursive });
                if (!analysisAux.isOwner(loggedUserID) && !loggedUserID.equals("admin")) {
                    throw new AccessControlException(
                            "Cannot update selected Analysis. Current user has not privileges over this element.");
                }

                if ("pending".equalsIgnoreCase(analysis.getStatus())) {
                    analysis.setStatus("open");
                }

                /**
                 * *******************************************************
                 * STEP 4 READ ALL STEPS AND CREATE THE LIST OF TASKS.
                 * *******************************************************
                 */
                ArrayList<Step> to_be_created_steps = new ArrayList<Step>();
                ArrayList<Step> to_be_updated_steps = new ArrayList<Step>();
                ArrayList<String> to_be_deleted_steps = new ArrayList<String>();

                for (Step step : analysis.getNonProcessedData()) {
                    if ("new_deleted".equals(step.getStatus())) {
                        continue; //ignore
                    } else if ("deleted".equals(step.getStatus()) || "edited_deleted".equals(step.getStatus())) {
                        to_be_deleted_steps.add(step.getStepID()); //DELETES THE STEP
                    } else if ("new".equals(step.getStatus())) {
                        to_be_created_steps.add(step); //CREATES THE STEP
                    } else {
                        if ("edited".equals(step.getStatus())) {
                            to_be_updated_steps.add(step);
                        }
                    }
                }

                for (Step step : analysis.getProcessedData()) {
                    if ("new_deleted".equals(step.getStatus())) {
                        continue; //ignore
                    } else if ("deleted".equals(step.getStatus()) || "edited_deleted".equals(step.getStatus())) {
                        to_be_deleted_steps.add(step.getStepID()); //DELETES THE STEP
                    } else if ("new".equals(step.getStatus())) {
                        to_be_created_steps.add(step); //CREATES THE STEP
                    } else {
                        if ("edited".equals(step.getStatus())) {
                            to_be_updated_steps.add(step);
                        }
                    }
                }

                /**
                 * *******************************************************
                 * STEP 5 GET ALL THE IDS FOR THE NEW STEPS AND UPDATE THE
                 * INFORMATION
                 * *******************************************************
                 */
                daoInstance1 = DAOProvider.getDAOByName("Analysis");
                daoInstance2 = DAOProvider.getDAOByName("Step");

                Collections.sort(to_be_created_steps);
                for (Step step : to_be_created_steps) {
                    String old_id = step.getStepID();
                    String new_id = daoInstance2.getNextObjectID(new Object[] { analysis.getAnalysisID() });
                    BLOCKED_IDs.add(new_id);

                    step.setStepID(new_id);
                    String[] usedData;
                    for (Step stepAux : analysis.getNonProcessedData()) {
                        if (stepAux instanceof IntermediateData) {
                            usedData = ((IntermediateData) stepAux).getUsedData();
                            int pos = Arrays.asList(usedData).indexOf(old_id);
                            if (pos != -1) {
                                usedData[pos] = new_id;
                            }
                        }

                    }
                    for (Step stepAux : analysis.getProcessedData()) {
                        if (stepAux instanceof ProcessedData) {
                            usedData = ((ProcessedData) stepAux).getUsedData();
                            int pos = Arrays.asList(usedData).indexOf(old_id);
                            if (pos != -1) {
                                usedData[pos] = new_id;
                            }
                        }
                    }
                }

                /**
                 * *******************************************************
                 * STEP 5 ADD, UPDATE AND REMOVE THE NPD instances IN DATABASE.
                 * Must be in this order because: -- If we change the used data
                 * for a specified step adding a to be created step, must be
                 * inserted first. -- If we change the used data removing an
                 * used step and then we delete this step (the used one), we
                 * must update first (because of foreign keys) With this method,
                 * when an step is removed, the step_id is lost. Because the
                 * "getNextStepID" function is called before removing ADDED
                 * steps must be ordered from less to greater step_number
                 * <p/>
                 * IF ERROR --> throws SQL Exception, GO TO STEP ? ELSE --> GO
                 * TO STEP 6
                 * *******************************************************
                 */
                daoInstance1.disableAutocommit();
                ROLLBACK_NEEDED = true;
                daoInstance1.update(analysis);

                /**
                 * *******************************************************
                 * STEP 6 APPLY THE STEP TASKS IN DATABASE. IF ERROR --> throws
                 * SQL Exception, GO TO STEP ? ELSE --> GO TO STEP 8
                 * *******************************************************
                 */
                ((Step_JDBCDAO) daoInstance2).insert(to_be_created_steps.toArray(new Step[] {}));
                ((Step_JDBCDAO) daoInstance2).remove(to_be_deleted_steps.toArray(new String[] {}));
                ((Step_JDBCDAO) daoInstance2).update(to_be_updated_steps.toArray(new Step[] {}));

                /**
                 * *******************************************************
                 * STEP 7 COMMIT CHANGES TO DATABASE. throws SQLException IF
                 * ERROR --> throws SQL Exception, GO TO STEP ? ELSE --> GO TO
                 * STEP 8
                 * *******************************************************
                 */
                daoInstance1.doCommit();
            } catch (Exception e) {
                if (e.getClass().getSimpleName().equals("MySQLIntegrityConstraintViolationException")) {
                    ServerErrorManager.handleException(null, null, null,
                            "Unable to update the Analysis information.");
                } else {
                    ServerErrorManager.handleException(e, Analysis_servlets.class.getName(),
                            "update_analysis_handler", e.getMessage());
                }
            } finally {
                /**
                 * *******************************************************
                 * STEP 7b CATCH ERROR, CLEAN CHANGES. throws SQLException
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());

                    for (String BLOCKED_ID : BLOCKED_IDs) {
                        BlockedElementsManager.getBlockedElementsManager().unlockID(BLOCKED_ID);
                    }
                    if (ROLLBACK_NEEDED) {
                        daoInstance1.doRollback();
                    }
                } else {
                    JsonObject obj = new JsonObject();
                    obj.add("success", new JsonPrimitive(true));
                    response.getWriter().print(obj.toString());
                }

                for (String BLOCKED_ID : BLOCKED_IDs) {
                    BlockedElementsManager.getBlockedElementsManager().unlockID(BLOCKED_ID);
                }

                /**
                 * *******************************************************
                 * STEP 9 Close connection.
                 * ********************************************************
                 */
                if (daoInstance1 != null) {
                    daoInstance1.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "update_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    /*------------------------------------------------------------------------------------------*
     *                                                                                          *
     * DELETE REQUEST HANDLERS                                                                  *
     *                                                                                          *
     *------------------------------------------------------------------------------------------*/
    private void delete_all_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
    }

    private void delete_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        try {
            boolean ROLLBACK_NEEDED = false;
            DAO daoInstance = null;
            boolean removable = true;
            String loggedUser = null;
            String analysisID = null;

            try {
                /**
                 * *******************************************************
                 * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF
                 * ERROR --> throws exception if not valid session, GO TO STEP
                 * ELSE --> GO TO STEP 2
                 * *******************************************************
                 */
                JsonParser parser = new JsonParser();
                JsonObject requestData = (JsonObject) parser.parse(request.getReader());

                loggedUser = requestData.get("loggedUser").getAsString();
                String sessionToken = requestData.get("sessionToken").getAsString();

                if (!checkAccessPermissions(loggedUser, sessionToken)) {
                    throw new AccessControlException("Your session is invalid. User or session token not allowed.");
                }

                String loggedUserID = requestData.get("loggedUserID").getAsString();
                String experimentID = requestData.get("currentExperimentID").getAsString();
                analysisID = requestData.get("analysis_id").getAsString();

                /**
                 * *******************************************************
                 * STEP 2 Get THE ANALYSIS Object from DB. IF ERROR --> throws
                 * MySQL exception, GO TO STEP 3b ELSE --> GO TO STEP 3
                 * *******************************************************
                 */
                boolean loadRecursive = true;
                Object[] params = { loadRecursive };
                daoInstance = DAOProvider.getDAOByName("Analysis");

                Analysis analysis = (Analysis) daoInstance.findByID(analysisID, params);
                if (!analysis.isOwner(loggedUserID) && !loggedUserID.equals("admin")) {
                    throw new AccessControlException(
                            "Cannot remove selected Analysis. Current user has not privileges over this element.");
                }

                /**
                 * *******************************************************
                 * STEP 3 Check if the user + the users in the remove_requests
                 * list are the owners for all the steps. If at least one of the
                 * steps has an user not in the list and the step is not
                 * imported, then we add the user to the remove_requests.
                 * Otherwise, we can remove the steps (or unlink) and the
                 * analysis.
                 * *******************************************************
                 */
                Set<String> users = new HashSet<String>(Arrays.asList(analysis.getRemoveRequests()));
                users.add(loggedUserID);

                //TODO: add admin user !loggedUserID.equalsIgnoreCase("admin")
                for (Step step : analysis.getNonProcessedData()) {
                    if (step.getAnalysisID().equalsIgnoreCase(analysisID)) { //If not imported step
                        boolean isOwner = false;
                        for (String user : users) { //Check if at least one of the users that want to remove is owner
                            isOwner = isOwner || step.isOwner(user);
                        }
                        if (!isOwner) {
                            removable = false;
                            break;
                        }
                    }
                }

                if (removable) {
                    for (Step step : analysis.getProcessedData()) {
                        if (step.getAnalysisID().equalsIgnoreCase(analysisID)) { //If not imported step
                            boolean isOwner = false;
                            for (String user : users) { //Check if at least one of the users that want to remove is owner
                                isOwner = isOwner || step.isOwner(user);
                            }
                            if (!isOwner) {
                                removable = false;
                                break;
                            }
                        }
                    }
                }

                /**
                 * *******************************************************
                 * STEP 4 If the analysis is removable, then we proceed to
                 * remove the analysis (includes unlinking shared steps).
                 * Otherwise, we update the list of remove_requests
                 * *******************************************************
                 */
                daoInstance = DAOProvider.getDAOByName("Analysis");
                daoInstance.disableAutocommit();
                ROLLBACK_NEEDED = true;

                if (removable) {
                    ((Analysis_JDBCDAO) daoInstance).remove(analysis);
                    //DELETE THE DATA DIRECTORY
                    File file = new File(
                            DATA_LOCATION + IMAGE_FILES_LOCATION.replaceAll("<experiment_id>", experimentID)
                                    + analysisID + "_prev.jpg");
                    if (file.exists()) {
                        file.delete();
                    }
                    file = new File(DATA_LOCATION + IMAGE_FILES_LOCATION.replaceAll("<experiment_id>", experimentID)
                            + analysisID + ".png");
                    if (file.exists()) {
                        file.delete();
                    }
                } else {
                    ((Analysis_JDBCDAO) daoInstance).updateRemoveRequests(analysisID,
                            users.toArray(new String[] {}));
                }

                /**
                 * *******************************************************
                 * STEP 5 COMMIT CHANGES TO DATABASE. throws SQLException IF
                 * ERROR --> throws SQL Exception, GO TO STEP ? ELSE --> GO TO
                 * STEP 6
                 * *******************************************************
                 */
                daoInstance.doCommit();
            } catch (Exception e) {
                ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "remove_analysis_handler",
                        e.getMessage());
            } finally {
                /**
                 * *******************************************************
                 * STEP 7b CATCH ERROR, CLEAN CHANGES. throws SQLException
                 * *******************************************************
                 */
                if (ServerErrorManager.errorStatus()) {
                    response.setStatus(400);
                    response.getWriter().print(ServerErrorManager.getErrorResponse());
                    if (ROLLBACK_NEEDED) {
                        daoInstance.doRollback();
                    }
                } else {
                    JsonObject obj = new JsonObject();
                    obj.add("success", new JsonPrimitive(true));
                    obj.add("removed", new JsonPrimitive(removable));
                    response.getWriter().print(obj.toString());
                }

                BlockedElementsManager.getBlockedElementsManager().unlockObject(analysisID, loggedUser);

                /**
                 * *******************************************************
                 * STEP 9 Close connection.
                 * ********************************************************
                 */
                if (daoInstance != null) {
                    daoInstance.closeConnection();
                }
            }
            //CATCH IF THE ERROR OCCURRED IN ROLL BACK OR CONNECTION CLOSE 
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "remove_analysis_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    //************************************************************************************
    //************************************************************************************
    //*****OTHER SERVLET HANDLERS ****************************************************
    //************************************************************************************
    //************************************************************************************
    private void lock_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        boolean alreadyLocked = false;
        String locker_id = "";
        ArrayList<String> notLockedSteps = new ArrayList<String>();

        try {
            JsonParser parser = new JsonParser();
            JsonObject requestData = (JsonObject) parser.parse(request.getReader());

            String loggedUser = requestData.get("loggedUser").getAsString();
            String sessionToken = requestData.get("sessionToken").getAsString();

            /**
             * *******************************************************
             * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF ERROR
             * --> throws exception if not valid session, GO TO STEP ELSE --> GO
             * TO STEP 2 *******************************************************
             */
            if (!checkAccessPermissions(loggedUser, sessionToken)) {
                throw new AccessControlException("Your session is invalid. User or session token not allowed.");
            }

            /**
             * *******************************************************
             * STEP 2 GET THE OBJECT ID AND TRY TO LOCK IT. IF ERROR --> throws
             * exception, GO TO STEP ELSE --> GO TO STEP 3
             * *******************************************************
             */
            String analysis_id = requestData.get("analysis_id").getAsString();
            alreadyLocked = !BlockedElementsManager.getBlockedElementsManager().lockObject(analysis_id, loggedUser);

            /**
             * *******************************************************
             * STEP 3 TRY TO LOCK THE STEPS. exception, GO TO STEP ELSE --> GO
             * TO STEP 3 *******************************************************
             */
            if (!alreadyLocked) {
                DAO dao_instance = DAOProvider.getDAOByName("Analysis");
                boolean loadRecursive = true;
                Object[] params = { loadRecursive };
                Analysis analysis = (Analysis) dao_instance.findByID(analysis_id, params);
                dao_instance.closeConnection();
                String step_id;
                for (Step step : analysis.getNonProcessedData()) {
                    step_id = step.getStepID();
                    if (!BlockedElementsManager.getBlockedElementsManager().lockObject(step_id, loggedUser)) {
                        notLockedSteps.add(step_id);
                    }
                }
                for (Step step : analysis.getProcessedData()) {
                    step_id = step.getStepID();
                    if (!BlockedElementsManager.getBlockedElementsManager().lockObject(step_id, loggedUser)) {
                        notLockedSteps.add(step_id);
                    }
                }

                //UNLOCK STEPS AND ANALYSIS
                if (notLockedSteps.size() > 0) {
                    BlockedElementsManager.getBlockedElementsManager().unlockObject(analysis_id, loggedUser);
                    for (Step step : analysis.getNonProcessedData()) {
                        BlockedElementsManager.getBlockedElementsManager().unlockObject(step.getStepID(),
                                loggedUser);
                    }
                    for (Step step : analysis.getProcessedData()) {
                        BlockedElementsManager.getBlockedElementsManager().unlockObject(step.getStepID(),
                                loggedUser);
                    }
                }
            } else {
                locker_id = BlockedElementsManager.getBlockedElementsManager().getLockerID(analysis_id);
            }
        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "lock_analysis_handler",
                    e.getMessage());
        } finally {
            /**
             * *******************************************************
             * STEP 4b CATCH ERROR. GO TO STEP 5
             * *******************************************************
             */
            if (ServerErrorManager.errorStatus()) {
                response.setStatus(400);
                response.getWriter().print(ServerErrorManager.getErrorResponse());
            } else {
                /**
                 * *******************************************************
                 * STEP 3A WRITE RESPONSE .
                 * *******************************************************
                 */
                JsonObject obj = new JsonObject();
                if (alreadyLocked) {
                    obj.add("success", new JsonPrimitive(false));
                    obj.add("reason", new JsonPrimitive(BlockedElementsManager.getErrorMessage()));
                    obj.add("user_id", new JsonPrimitive(locker_id));
                } else if (notLockedSteps.size() > 0) {
                    JsonArray _notLockedSteps = new JsonArray();
                    obj.add("success", new JsonPrimitive(false));
                    obj.add("reason", new JsonPrimitive("Some of the steps are locked by other users"));
                    for (String step_id : notLockedSteps) {
                        _notLockedSteps.add(new JsonPrimitive(step_id));
                    }
                    obj.add("notLockedSteps", _notLockedSteps);

                } else {
                    obj.add("success", new JsonPrimitive(true));
                }
                response.getWriter().print(obj.toString());
            }
        }
    }

    private void unlock_analysis_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        boolean alreadyUnlocked = false;
        ArrayList<String> notUnlockedSteps = new ArrayList<String>();

        try {
            JsonParser parser = new JsonParser();
            JsonObject requestData = (JsonObject) parser.parse(request.getReader());

            String loggedUser = requestData.get("loggedUser").getAsString();
            String sessionToken = requestData.get("sessionToken").getAsString();

            /**
             * *******************************************************
             * STEP 1 CHECK IF THE USER IS LOGGED CORRECTLY IN THE APP. IF ERROR
             * --> throws exception if not valid session, GO TO STEP ELSE --> GO
             * TO STEP 2 *******************************************************
             */
            if (!checkAccessPermissions(loggedUser, sessionToken)) {
                throw new AccessControlException("Your session is invalid. User or session token not allowed.");
            }

            /**
             * *******************************************************
             * STEP 2 GET THE OBJECT ID AND TRY TO UNLOCK IT. IF ERROR -->
             * throws exception, GO TO STEP ELSE --> GO TO STEP 3
             * *******************************************************
             */
            String analysis_id = requestData.get("analysis_id").getAsString();
            alreadyUnlocked = !BlockedElementsManager.getBlockedElementsManager().unlockObject(analysis_id,
                    loggedUser);

            /**
             * *******************************************************
             * STEP 3 TRY TO UNLOCK THE STEPS. exception, GO TO STEP ELSE --> GO
             * TO STEP 3 *******************************************************
             */
            DAO dao_instance = DAOProvider.getDAOByName("Analysis");
            boolean loadRecursive = true;
            Object[] params = { loadRecursive };
            Analysis analysis = (Analysis) dao_instance.findByID(analysis_id, params);
            dao_instance.closeConnection();
            if (analysis != null) {
                String step_id;
                for (Step step : analysis.getNonProcessedData()) {
                    step_id = step.getStepID();
                    if (!BlockedElementsManager.getBlockedElementsManager().unlockObject(step_id, loggedUser)) {
                        notUnlockedSteps.add(step_id);
                    }
                }
                for (Step step : analysis.getProcessedData()) {
                    step_id = step.getStepID();
                    if (!BlockedElementsManager.getBlockedElementsManager().unlockObject(step_id, loggedUser)) {
                        notUnlockedSteps.add(step_id);
                    }
                }
            }

        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "unlock_analysis_handler",
                    e.getMessage());
        } finally {
            /**
             * *******************************************************
             * STEP 3b CATCH ERROR.
             * *******************************************************
             */
            if (ServerErrorManager.errorStatus()) {
                response.setStatus(400);
                response.getWriter().print(ServerErrorManager.getErrorResponse());
            } else {
                /**
                 * *******************************************************
                 * STEP 3A WRITE RESPONSE .
                 * *******************************************************
                 */
                JsonObject obj = new JsonObject();
                if (alreadyUnlocked) {
                    obj.add("success", new JsonPrimitive(false));
                    obj.add("reason", new JsonPrimitive(BlockedElementsManager.getErrorMessage()));
                } else {
                    obj.add("success", new JsonPrimitive(true));

                    if (notUnlockedSteps.size() > 0) {
                        JsonArray _notUnlockedSteps = new JsonArray();
                        for (String step_id : notUnlockedSteps) {
                            _notUnlockedSteps.add(new JsonPrimitive(step_id));
                        }
                        obj.add("notUnlockedSteps", _notUnlockedSteps);
                    }
                }
                response.getWriter().print(obj.toString());
            }
        }
    }

    private void getAnalysisPreviewImageHandler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        String analysisID = request.getParameter("analysis_id");
        String experiment_id = request.getParameter("experimentID");

        try {
            File file = new File(DATA_LOCATION + IMAGE_FILES_LOCATION.replaceAll("<experiment_id>", experiment_id)
                    + analysisID + "_prev.jpg");

            if (file.exists()) {
                response.reset();
                response.addHeader("Access-Control-Allow-Origin", "*");

                response.setContentType("image/jpeg");
                response.addHeader("Content-Disposition", "attachment; filename=" + analysisID + "_prev.jpg");
                response.setContentLength((int) file.length());

                FileInputStream fileInputStream = new FileInputStream(file);
                OutputStream responseOutputStream = response.getOutputStream();
                int bytes;
                while ((bytes = fileInputStream.read()) != -1) {
                    responseOutputStream.write(bytes);
                }
                responseOutputStream.close();
            }
        } catch (NullPointerException e) {
            ServerErrorManager.addErrorMessage(4, Analysis_servlets.class.getName(),
                    "get_analysis_img_prev_handler", e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        } catch (Exception e) {
            ServerErrorManager.addErrorMessage(4, Analysis_servlets.class.getName(),
                    "get_analysis_img_prev_handler", e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    private void getAnalysisImageHandler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        String analysis_id = request.getParameter("analysis_id");
        String experiment_id = request.getParameter("experimentID");

        try {
            File file = new File(DATA_LOCATION + IMAGE_FILES_LOCATION.replaceAll("<experiment_id>", experiment_id)
                    + analysis_id + ".png");

            if (file.exists()) {
                response.reset();
                response.addHeader("Access-Control-Allow-Origin", "*");

                response.setContentType("image/png");
                response.addHeader("Content-Disposition", "attachment; filename=" + analysis_id + ".png");
                response.setContentLength((int) file.length());

                FileInputStream fileInputStream = new FileInputStream(file);
                OutputStream responseOutputStream = response.getOutputStream();
                int bytes;
                while ((bytes = fileInputStream.read()) != -1) {
                    responseOutputStream.write(bytes);
                }

                responseOutputStream.close();
            }
        } catch (NullPointerException e) {
            ServerErrorManager.addErrorMessage(4, Analysis_servlets.class.getName(), "get_analysis_img_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        } catch (Exception e) {
            ServerErrorManager.addErrorMessage(4, Analysis_servlets.class.getName(), "get_analysis_img_handler",
                    e.getMessage());
            response.setStatus(400);
            response.getWriter().print(ServerErrorManager.getErrorResponse());
        }
    }

    private void get_step_subtypes_handler(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        ArrayList<String> subtypes = new ArrayList<String>();
        try {
            String step_type = request.getParameter("step_type");

            String path = Analysis_servlets.class.getResource("/../../data/templates/" + step_type).getPath();
            File folder = new File(path);

            String filename;
            for (File fileEntry : folder.listFiles()) {
                if (!fileEntry.isDirectory()) {
                    filename = fileEntry.getName();
                    filename = filename.replaceAll("_", " ");
                    filename = filename.replace("-form.json", "");
                    //                    filename = filename.substring(0, 1).toUpperCase() + filename.substring(1);
                    subtypes.add(filename);
                }
            }

        } catch (Exception e) {
            ServerErrorManager.handleException(e, Analysis_servlets.class.getName(), "get_step_subtypes_handler",
                    e.getMessage());
        } finally {
            /**
             * *******************************************************
             * STEP 3b CATCH ERROR. GO TO STEP 4
             * *******************************************************
             */
            if (ServerErrorManager.errorStatus()) {
                response.setStatus(400);
                response.getWriter().print(ServerErrorManager.getErrorResponse());
            } else {
                /**
                 * *******************************************************
                 * STEP 3A WRITE SUCCESS RESPONSE. GO TO STEP 4
                 * *******************************************************
                 */
                JsonObject obj = new JsonObject();
                JsonArray _subtypes = new JsonArray();
                for (String subtype : subtypes) {
                    _subtypes.add(new JsonPrimitive(subtype));
                }
                obj.add("subtypes", _subtypes);
                response.getWriter().print(obj.toString());
            }
        }
    }

}