Package uk.ac.bbsrc.tgac.miso.spring.ajax

Source Code of uk.ac.bbsrc.tgac.miso.spring.ajax.SubmissionControllerHelperService

/*
* Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK
* MISO project contacts: Robert Davey, Mario Caccamo @ TGAC
* *********************************************************************
*
* This file is part of MISO.
*
* MISO 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.
*
* MISO 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 MISO.  If not, see <http://www.gnu.org/licenses/>.
*
* *********************************************************************
*/

package uk.ac.bbsrc.tgac.miso.spring.ajax;

import com.eaglegenomics.simlims.core.manager.SecurityManager;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sourceforge.fluxion.ajax.Ajaxified;
import net.sourceforge.fluxion.ajax.util.JSONUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import uk.ac.bbsrc.tgac.miso.core.data.*;
import uk.ac.bbsrc.tgac.miso.core.data.Project;
import uk.ac.bbsrc.tgac.miso.core.data.impl.LibraryDilution;
import uk.ac.bbsrc.tgac.miso.core.data.impl.PartitionImpl;
import uk.ac.bbsrc.tgac.miso.core.data.impl.PoolImpl;
import uk.ac.bbsrc.tgac.miso.core.data.impl.SubmissionImpl;
import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType;
import uk.ac.bbsrc.tgac.miso.core.data.type.SubmissionActionType;
import uk.ac.bbsrc.tgac.miso.core.exception.SubmissionException;
import uk.ac.bbsrc.tgac.miso.core.manager.MisoFilesManager;
import uk.ac.bbsrc.tgac.miso.core.manager.RequestManager;
import uk.ac.bbsrc.tgac.miso.core.manager.SubmissionManager;
import uk.ac.bbsrc.tgac.miso.core.service.submission.*;
import uk.ac.bbsrc.tgac.miso.core.util.FormUtils;
import uk.ac.bbsrc.tgac.miso.core.util.LimsUtils;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* uk.ac.bbsrc.tgac.miso.spring.ajax
* <p/>
* Info
*
* @author Rob Davey
* @since 0.0.2
*/
@Ajaxified
public class SubmissionControllerHelperService {
  protected static final Logger log = LoggerFactory.getLogger(SubmissionControllerHelperService.class);
  @Autowired
  private SecurityManager securityManager;
  @Autowired
  private RequestManager requestManager;
  @Autowired
  private SubmissionManager submissionManager;
  @Autowired
  private MisoFilesManager misoFileManager;
  @Autowired
  private FilePathGeneratorResolverService filePathGeneratorResolverService;

  private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

  //Saves a new submission to the DB, or updates an existing submission, based on details sent vie AJAX from
  //editSubmission.jsp
  public JSONObject saveSubmission(HttpSession session, JSONObject json) {
    try {
      if (json.has("form") && !json.get("form").equals("")) {
        //creates a new submission object using the form info
        Submission newSubmission = new SubmissionImpl();
        //if editing an existing submission
        if (json.has("submissionId") && json.get("submissionId") != "" && !json.get("submissionId").equals(-1)) {
          //calls up the existing submission with this ID
          Submission oldSubmission = requestManager.getSubmissionById(Long.parseLong(json.getString("submissionId")));
          //sets the details of the new one to match the old.
          newSubmission.setId(oldSubmission.getId());
          newSubmission.setAccession(oldSubmission.getAccession());
          //newSubmission.setAlias(oldSubmission.getAlias());
          newSubmission.setCreationDate(oldSubmission.getCreationDate());
          //newSubmission.setDescription(oldSubmission.getDescription());
          newSubmission.setName(oldSubmission.getName());
          newSubmission.setSubmissionDate(oldSubmission.getSubmissionDate());
          //newSubmission.setTitle(oldSubmission.getTitle());
          newSubmission.setVerified(oldSubmission.isVerified());
          newSubmission.setCompleted(oldSubmission.isCompleted());
        }

        //sets the title, alias and description based on form contents
        JSONArray form = JSONArray.fromObject(json.get("form"));
        Set<SequencerPoolPartition> newPartitions = new HashSet<SequencerPoolPartition>();

        for (JSONObject j : (Iterable<JSONObject>) form) {
          if (j.getString("name").equals("title")) {
            newSubmission.setTitle(j.getString("value"));
          }
          if (j.getString("name").equals("alias")) {
            newSubmission.setAlias(j.getString("value"));
          }
          if (j.getString("name").equals("description")) {
            newSubmission.setDescription(j.getString("value"));
          }

          if (j.getString("name").contains("DIL")) {
            Long dilutionId = Long.parseLong(j.getString("name").replaceAll("\\D+", ""));
            Long partitionId = Long.parseLong(j.getString("value").replaceAll("\\D+", ""));
            //and a new Partition created from the ID
            PartitionImpl newPartition = new PartitionImpl();
            newPartition.setId(partitionId);
            //if the partition is not already in the set of newPartitions:
            if (newPartitions.add(newPartition)) {
              // a new pool is created
              Pool<Dilution> newPool = new PoolImpl<Dilution>();
              //details of the original partition's pool are copied to the new one
              Pool<? extends Poolable> oldPool = requestManager.getSequencerPoolPartitionById(partitionId).getPool();
              newPool.setExperiments(oldPool.getExperiments());
              newPool.setPlatformType(oldPool.getPlatformType());
              //the new pool is added to the partition
              newPartition.setPool(newPool);
            }

            for (SequencerPoolPartition nextPartition : newPartitions) {
              if (nextPartition.getId() == partitionId) {
                //Dilution dilution = requestManager.getDilutionByIdAndPlatform(dilutionId, nextPartition.getPool().getPlatformType());
                Dilution dilution = requestManager.getLibraryDilutionById(dilutionId);
                Pool pool = nextPartition.getPool();
                pool.addPoolableElement(dilution);
              }
            }
          }
        }
        //the set of partitions is added to the new Submission
        for (SequencerPoolPartition sequencerPoolPartition : newPartitions) {
          newSubmission.addSubmissionElement(sequencerPoolPartition);
        }
        //the submission is saved
        requestManager.saveSubmission(newSubmission);
        return JSONUtils.SimpleJSONResponse("Submission " + newSubmission.getId() + " saved!");
      }
    }
    catch (Exception e) {
      e.printStackTrace();
      return JSONUtils.SimpleJSONError(e.getMessage());
    }
    return JSONUtils.SimpleJSONResponse("saveSubmission called");
  }

  public JSONObject previewSubmissionMetadata(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("")) {
        Long submissionId = ((Integer) json.get("submissionId")).longValue();
        Submission<Submittable, Document, Document> submission = requestManager.getSubmissionById(submissionId);

        SubmissionActionType action = SubmissionActionType.VALIDATE;
        if (json.has("operation")) {
          action = SubmissionActionType.valueOf(json.getString("operation"));
        }
        submission.setSubmissionActionType(action);

        try {
          String s = submissionManager.generateSubmissionMetadata(submission);
          return JSONUtils.JSONObjectResponse("metadata", s);
        }
        catch (SubmissionException se) {
          return JSONUtils.SimpleJSONError(se.getMessage());
        }
      }
    }
    catch (Exception e) {
      log.debug("Failed to get submission metadata: ", e);
      return JSONUtils.SimpleJSONError("Failed to get submission metadata");
    }
    return JSONUtils.SimpleJSONError("Cannot build submission metadata");
  }

  public JSONObject downloadSubmissionMetadata(HttpSession session, JSONObject json) {
    Long submissionId = json.getLong("submissionId");

    try {
      Submission submission = requestManager.getSubmissionById(submissionId);
      Collection<File> files = misoFileManager.getFiles(Submission.class, submission.getName());

      Date latestDate = null;

      //get latest submitted xmls
      try {
        for (File f : files) {
          if (f.getName().contains("submission_")) {
            String d = f.getName().substring(f.getName().lastIndexOf("_")+1, f.getName().lastIndexOf("."));
            Date test =  df.parse(d);
            if (latestDate == null || test.after(latestDate)) {
              latestDate = test;
            }
          }
        }
      }
      catch (ParseException e) {
        log.error("No timestamped submission metadata documents. Falling back to simple names: " + e.getMessage());
      }

      String dateStr = "";
      if (latestDate != null) {
        dateStr = "_"+df.format(latestDate);
      }

      Set<File> filesToZip = new HashSet<File>();
      for (File f : files) {
        if (!"".equals(dateStr) && f.getName().contains(dateStr) && f.getName().endsWith(".xml")) {
          filesToZip.add(f);
        }
      }

      File zipFile = misoFileManager.getNewFile(Submission.class, submission.getName(), "bundle"+dateStr+".zip");
      LimsUtils.zipFiles(filesToZip, zipFile);

      File f = misoFileManager.getFile(
              Submission.class,
              submission.getName(),
              zipFile.getName());

      return JSONUtils.SimpleJSONResponse("" + f.getName().hashCode());
    }
    catch (Exception e) {
      e.printStackTrace();
      return JSONUtils.SimpleJSONError("Failed to generate submission metadata zip file: " + e.getMessage());
    }
  }

  /*
  generates SubmissionMetadata from the submission Object, sets the action to 'validate'
  submits metadata to SRA and parses feedback
  */
  public JSONObject validateSubmissionMetadata(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("")) {
        Long submissionId = ((Integer) json.get("submissionId")).longValue();
        Submission<Submittable, Document, Document> submission = requestManager.getSubmissionById(submissionId);
        SubmissionActionType action = SubmissionActionType.VALIDATE;
        if (json.has("operation")) {
          action = SubmissionActionType.valueOf(json.getString("operation"));
        }
        submission.setSubmissionActionType(action);
        try {
          String s = submissionManager.generateSubmissionMetadata(submission);
        }
        catch (SubmissionException se) {
          return JSONUtils.SimpleJSONError(se.getMessage());
        }
        Document report = submission.submit(submissionManager);
        if (report != null) {
          Map<String, Object> responseMap = (Map<String, Object>) submissionManager.parseResponse(report);
          return JSONUtils.JSONObjectResponse(responseMap);
        }
        else {
          return JSONUtils.SimpleJSONError("Failed to get submission report. Something went wrong in the submission process");
        }
      }
    }
    catch (Exception e) {
      log.debug("Failed to get submission metadata: ", e);
      return JSONUtils.SimpleJSONError("Failed to get submission metadata");
    }
    return JSONUtils.SimpleJSONError("Cannot build submission metadata");
  }

  public JSONObject submitSubmissionMetadata(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("")) {
        Long submissionId = ((Integer) json.get("submissionId")).longValue();
        Submission submission = requestManager.getSubmissionById(submissionId);

        //if no action is specified, validate. otherwise, set the action type.
        SubmissionActionType action = SubmissionActionType.VALIDATE;
        if (json.has("operation")) {
          action = SubmissionActionType.valueOf(json.getString("operation"));
        }

        submission.setSubmissionActionType(action);
        Document report = (Document) submission.submit(submissionManager);

        if (report != null) {
          Map<String, Object> responseMap = (Map<String, Object>) submissionManager.parseResponse(report);
          return JSONUtils.JSONObjectResponse(responseMap);
        }
        else {
          return JSONUtils.SimpleJSONError("Failed to get submission report. Something went wrong in the submission process");
        }
      }
    }
    catch (Exception e) {
      log.debug("Failed to get submission metadata: ", e);
      return JSONUtils.SimpleJSONError("Failed to get submission metadata");
    }
    return JSONUtils.SimpleJSONError("Cannot build submission metadata");
  }

  public JSONObject submitSequenceData(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("")) {
        Long submissionId = ((Integer) json.get("submissionId")).longValue();
        Submission<Submittable, Document, Document> submission = requestManager.getSubmissionById(submissionId);
        String response = submissionManager.submitSequenceData(submission);
        return (JSONUtils.SimpleJSONResponse(response));
      }
      else {
        return JSONUtils.SimpleJSONError("Failed to get submission report. Something went wrong in the sequence Data submission process");
      }
    }
    catch (Exception e) {
      log.debug("Failed to submit sequence data: ", e);
      return JSONUtils.SimpleJSONError("Failed to submit sequence data");
    }
  }

  public JSONObject checkUploadProgress(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("")/*&& !json.get("submissionId").equals(null)*/) {
        Long submissionId = json.getLong("submissionId");
        Map<String, Object> responseMap;
        JSONObject report = new JSONObject();

        JSONArray jsonUploadJobs = new JSONArray();
        //TODO - get upload report
        UploadReport uploadReport = submissionManager.getUploadProgress(submissionId);
        if (uploadReport != null) {
          List<UploadJob> uploads = uploadReport.getUploadJobs();

          for (UploadJob u : uploads) {
            JSONObject jsonUpload = new JSONObject();
            jsonUpload.put("filename", u.getFile().getName());
            jsonUpload.put("percent", u.getPercentageTransferred());
            jsonUploadJobs.add(jsonUpload);
          }

          report.put("status", uploadReport.getStatus());
          report.put("message", uploadReport.getMessage());
          report.put("uploadJobs", jsonUploadJobs);
          return report;
        }
        else {
          return JSONUtils.SimpleJSONResponse("sorry- no upload report has been returned!");
        }
      }
    }
    catch (Exception e) {
      log.debug("Failed to get upload progress ", e);
      e.printStackTrace();
      return JSONUtils.SimpleJSONError("Failed to get upload report" + e.getMessage());
    }
    log.debug("Failed to get upload progress ");
    return JSONUtils.SimpleJSONError("Failed to get upload progress");
  }

  public JSONObject openSubmissionProjectNodes(HttpSession session, JSONObject json) {
    try {
      if (json.has("submissionId") && !json.get("submissionId").equals("") && !json.get("submissionId").equals(null)) {
        Long submissionId = json.getLong("submissionId");
        Map<String, Object> responseMap = new HashMap<String, Object>();

        //TODO - get projects from submission
        Submission sub = requestManager.getSubmissionById(submissionId);
        Set<Long> projectIds = new HashSet<Long>();
        for (Object o : sub.getSubmissionElements()) {
          if (o instanceof Project) {
            projectIds.add(((Project) o).getProjectId());
          }

          if (o instanceof Study) {
            projectIds.add(((Study) o).getProject().getProjectId());
          }

          if (o instanceof Experiment) {
            projectIds.add(((Experiment) o).getStudy().getProject().getProjectId());
          }

          if (o instanceof Sample) {
            projectIds.add(((Sample) o).getProject().getProjectId());
          }
        }
        responseMap.put("projects", JSONArray.fromObject(projectIds));
        return JSONUtils.JSONObjectResponse(responseMap);
      }
    }
    catch (Exception e) {
      log.debug("Failed to open project nodes for submission: ", e);
      return JSONUtils.SimpleJSONError("Failed to open project nodes for submission");
    }
    return JSONUtils.SimpleJSONError("Cannot open project nodes for submission");
  }

  //creates the list of runs, partitions and submittable dilutions for a project, to be displayed on
  //editSubmission.jsp when the project is clicked. Also checks the boxes next to any dilutions
  //that are already in the submission.
  public JSONObject populateSubmissionProject(HttpSession session, JSONObject json) {
    try {
      //gets the submission from the database
      Submission sub = null;
      if (json.has("submissionId") && !json.get("submissionId").equals("")) {
        sub = requestManager.getSubmissionById(json.getLong("submissionId"));
      }
      //gets studies and experiments for the project that has been selected
      if (json.has("projectId") && !json.get("projectId").equals("")) {
        StringBuilder sb = new StringBuilder();
        Long projectId = json.getLong("projectId");

        Project p = requestManager.getProjectById(projectId);
        for (Study s : p.getStudies()) {
          Collection<Experiment> experiments = requestManager.listAllExperimentsByStudyId(s.getId());
          s.setExperiments(experiments);
        }
        //gets the runs for the project
        List<Run> runs = new ArrayList<Run>(requestManager.listAllRunsByProjectId(projectId));
        Collections.sort(runs);

        //creates HTML list of runs
        if (runs.size() > 0) {
          sb.append("<ul id='runList" + projectId + "'>");
          for (Run r : runs) {
            sb.append("<li>");
            sb.append("<a href='/miso/run/" + r.getId() + "'><b>" + r.getName() + "</b> : " + r.getAlias() + "</a>");
            sb.append("<input type='hidden' id='RUN_"+r.getId()+"' name='RUN_"+r.getId()+"' value='"+r.getId()+"'/>");
            sb.append("<ul>");

            //creates HTML list of partition containers for each run
            Collection<SequencerPartitionContainer<SequencerPoolPartition>> partitionContainers = requestManager.listSequencerPartitionContainersByRunId(r.getId());
            for (SequencerPartitionContainer<SequencerPoolPartition> partitionContainer : partitionContainers) {
              sb.append("<li>");
              sb.append("<b>" + partitionContainer.getIdentificationBarcode() + "</b> : " + partitionContainer.getId());
              sb.append("<ul>");

              //creates HTML list of partitions for each partition container
              Collection<SequencerPoolPartition> partitions = partitionContainer.getPartitions();
              for (SequencerPoolPartition part : partitions) {

                // Checks whether the partition was involved in the project.
                boolean partitionInvolved = false;
                if (part.getPool() != null) {
                  Collection<Experiment> exps = part.getPool().getExperiments();
                  List<String> involvedExperiments = new ArrayList<String>();
                  for (Experiment e : exps) {
                    if (e.getStudy().getProject().getProjectId().equals(p.getProjectId())) {
                      involvedExperiments.add(e.getStudy().getProject().getAlias());
                      partitionInvolved = true;
                    }
                  }

                  if (partitionInvolved) {
                    //If the partition was involved in the project, it is listed
                    sb.append("<li><input type='checkbox' id='" + r.getId() + "_" + partitionContainer.getId() + "_" + part.getPartitionNumber() + "' name='partition' " +
                              "itemLabel='" + part.getPartitionNumber() + "' itemValue='PAR" + part.getId() + "' value='PAR" + part.getId() + "' onclick='Submission.ui.togglePartitionContents(this)'");

                    if (sub != null) {
                      // checks checkboxes if the partition is in the submission
                      if (sub != null && !sub.getSubmissionElements().isEmpty() && sub.getSubmissionElements().contains(part)) {
                        sb.append(" checked='checked' ");
                      }
                    }

                    sb.append("/>");
                    //adds the Partition info: number, name, experiments etc.
                    sb.append("<b>Partition " + part.getPartitionNumber() + "</b> : " + part.getPool().getName() + " (" + LimsUtils.join(involvedExperiments, ",") + ")");

                    //creates HTML for list of library dilutions and corresponding datafiles.
                    //gets all the dilutions in that partition's pool.
                    List<? extends Poolable> poolables = new ArrayList<Poolable>(part.getPool().getPoolableElements());
                    Collections.sort(poolables);

                    FilePathGenerator fpg = filePathGeneratorResolverService.getFilePathGenerator(r.getPlatformType());
                    if (fpg == null) {
                      log.warn("No file path generator found for '"+r.getPlatformType().getKey()+"'. Falling back to fake path generator.");
                      fpg = new FakeFilepathGenerator();
                    }

                    sb.append("<ul>");

                    for (Poolable d : poolables) {
                      sb.append("<li><input type='checkbox'  name='DIL_" + d.getId() + "' id='DIL" + d.getId() + "_PAR" + part.getId() + "' value='PAR_" + part.getId() + "' ");

                      if (sub != null && sub.getSubmissionElements().contains(part)) {
                        //checks dilution checkboxes if dilution is in the submission
                        for (Object o : sub.getSubmissionElements()) {
                          if (o.equals(part)) {
                            SequencerPoolPartition subPart = (SequencerPoolPartition) o;
                            for (Poolable bla : subPart.getPool().getPoolableElements()) {
                              if (bla.getClass().equals(d.getClass()) && bla.getId() == d.getId()) {
                                sb.append(" checked='checked' ");
                              }
                            }
                          }
                        }
                      }

                      if (d instanceof Dilution) {
                        sb.append(">" + partitionContainer.getId() + "_" + ((Dilution)d).getLibrary().getName() + "_" + d.getName() + ": ");
                        sb.append("<ul>");
                        try {
                          for (File f : fpg.generateFilePath(part, (Dilution)d)) {
                            sb.append("<li>" + f.getName() + "</li>");
                          }
                        }
                        catch (SubmissionException e1) {
                          log.debug("Failed to generate path for data file in submission: ", e1);
                          e1.printStackTrace();
                          return JSONUtils.SimpleJSONError("Failed to populate project for submission");
                        }
                        sb.append("</ul>");
                      }
                      else if (d instanceof Plate) {
                        sb.append(">" + partitionContainer.getId() + "_" + d.getName() + ": ");
                        /*
                        sb.append("<ul>");
                        try {
                          for (File f : fpg.generateFilePath(part, (Plate)d)) {
                            sb.append("<li>" + f.getName() + "</li>");
                          }
                        }
                        catch (SubmissionException e1) {
                          log.debug("Failed to generate path for data file in submission: ", e1);
                          e1.printStackTrace();
                          return JSONUtils.SimpleJSONError("Failed to populate project for submission");
                        }
                        sb.append("</ul>");
                        */
                      }

                      sb.append("</li>");
                    }
                     //end dilutions
                    sb.append("</ul>");
                    sb.append("</li>");
                  }
                }
              }
              sb.append("</ul>");
              sb.append("</li>");
            }
            sb.append("</ul>");
            sb.append("</li>");
          }
          sb.append("</ul>");
        }
        else {
          sb.append("<ul id='runList" + projectId + "'>");
          sb.append("Project " + projectId + " contains no submittable elements.");
          sb.append("</ul>");
        }
        return JSONUtils.JSONObjectResponse("html", sb.toString());
      }
    }
    catch (IOException e) {
      log.debug("Failed to populate project for submission: ", e);
      e.printStackTrace();
      return JSONUtils.SimpleJSONError("Failed to populate project for submission");
    }
    return JSONUtils.SimpleJSONError("Cannot populate project for submission");
  }

  public void setSecurityManager(SecurityManager securityManager) {
    this.securityManager = securityManager;
  }

  public void setRequestManager(RequestManager requestManager) {
    this.requestManager = requestManager;
  }

  public void setSubmissionManager(SubmissionManager submissionManager) {
    this.submissionManager = submissionManager;
  }

  public void setMisoFileManager(MisoFilesManager misoFileManager) {
    this.misoFileManager = misoFileManager;
  }

  public void setFilePathGeneratorResolverService(FilePathGeneratorResolverService filePathGeneratorResolverService) {
    this.filePathGeneratorResolverService = filePathGeneratorResolverService;
  }
}
TOP

Related Classes of uk.ac.bbsrc.tgac.miso.spring.ajax.SubmissionControllerHelperService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.