/* * Copyright (C) 2011 SeqWare * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.seqware.webservice.resources.tables; import java.io.IOException; import java.sql.SQLException; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import net.sf.beanlib.CollectionPropertyName; import net.sf.beanlib.hibernate3.Hibernate3DtoCopier; import net.sourceforge.seqware.common.business.IUSService; import net.sourceforge.seqware.common.business.LaneService; import net.sourceforge.seqware.common.business.WorkflowRunService; import net.sourceforge.seqware.common.business.WorkflowService; import net.sourceforge.seqware.common.factory.BeanFactory; import net.sourceforge.seqware.common.factory.DBAccess; import net.sourceforge.seqware.common.model.IUS; import net.sourceforge.seqware.common.model.Lane; import net.sourceforge.seqware.common.model.Processing; import net.sourceforge.seqware.common.model.Registration; import net.sourceforge.seqware.common.model.Workflow; import net.sourceforge.seqware.common.model.WorkflowRun; import net.sourceforge.seqware.common.model.WorkflowRunParam; import net.sourceforge.seqware.common.util.Log; import net.sourceforge.seqware.common.util.maptools.MapTools; import net.sourceforge.seqware.common.util.xmltools.JaxbObject; import net.sourceforge.seqware.common.util.xmltools.XmlTools; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.resource.Get; import org.restlet.resource.ResourceException; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * <p> * WorkflowRunIDResource class. * </p> * * @author mtaschuk * @version $Id: $Id */ public class WorkflowRunIDResource extends DatabaseIDResource { /** * <p> * Constructor for WorkflowRunIDResource. * </p> */ public WorkflowRunIDResource() { super("workflowRunId"); } /** * <p> * getXml. * </p> */ @Get public void getXml() { authenticate(); Hibernate3DtoCopier copier = new Hibernate3DtoCopier(); JaxbObject<WorkflowRun> jaxbTool = new JaxbObject<>(); WorkflowRunService ss = BeanFactory.getWorkflowRunServiceBean(); WorkflowRun workflowRun = getWorkflowRun(ss); // specify that we want the input file set to be copied along, if this works, we should clean up the manual copying below CollectionPropertyName<WorkflowRun>[] createCollectionPropertyNames = CollectionPropertyName.createCollectionPropertyNames( WorkflowRun.class, new String[] { "inputFileAccessions", "workflowRunAttributes" }); WorkflowRun dto = copier.hibernate2dto(WorkflowRun.class, workflowRun, ArrayUtils.EMPTY_CLASS_ARRAY, createCollectionPropertyNames); // Log.debug("getXML() Workflow run contains " + workflowRun.getInputFileAccessions().size() + " input files"); // dto.setInputFileAccessions(workflowRun.getInputFileAccessions()); if (fields.contains("lanes")) { SortedSet<Lane> lanes = workflowRun.getLanes(); if (lanes != null) { SortedSet<Lane> copiedLanes = new TreeSet<>(); for (Lane lane : lanes) { copiedLanes.add(copier.hibernate2dto(Lane.class, lane)); } dto.setLanes(copiedLanes); } else { Log.info("Could not be found: lanes"); } } if (fields.contains("ius")) { SortedSet<IUS> iuses = workflowRun.getIus(); if (iuses != null) { SortedSet<IUS> copiedIUS = new TreeSet<>(); for (IUS i : iuses) { copiedIUS.add(copier.hibernate2dto(IUS.class, i)); } dto.setIus(copiedIUS); } else { Log.info("Could not be found: ius"); } } if (fields.contains("processes")) { SortedSet<Processing> procs = workflowRun.getProcessings(); if (procs != null) { SortedSet<Processing> copiedPs = new TreeSet<>(); for (Processing p : procs) { copiedPs.add(copier.hibernate2dto(Processing.class, p)); } dto.setProcessings(copiedPs); } else { Log.info("Could not be found: processings"); } procs = workflowRun.getOffspringProcessings(); if (procs != null) { SortedSet<Processing> copiedPs = new TreeSet<>(); for (Processing p : procs) { copiedPs.add(copier.hibernate2dto(Processing.class, p)); } dto.setOffspringProcessings(copiedPs); } else { Log.info("Could not be found: offspring processings"); } } Document line = XmlTools.marshalToDocument(jaxbTool, dto); getResponse().setEntity(XmlTools.getRepresentation(line)); } /** * <p> * updateWorkflowRun. * </p> * * @param newWR * a {@link net.sourceforge.seqware.common.model.WorkflowRun} object. * @return a {@link net.sourceforge.seqware.common.model.WorkflowRun} object. * @throws org.restlet.resource.ResourceException * if any. * @throws java.sql.SQLException * if any. */ public WorkflowRun updateWorkflowRun(WorkflowRun newWR) throws ResourceException, SQLException { authenticate(); WorkflowRunService wrs = BeanFactory.getWorkflowRunServiceBean(); WorkflowRun wr = testIfNull(wrs.findBySWAccession(newWR.getSwAccession())); wr.givesPermission(registration); // ius_workflow_runs if (newWR.getIus() != null) { SortedSet<IUS> iuses = newWR.getIus(); if (iuses != null) { SortedSet<IUS> set = new TreeSet<>(); for (IUS ius : iuses) { IUSService is = BeanFactory.getIUSServiceBean(); IUS newI = is.findBySWAccession(ius.getSwAccession()); newI.givesPermission(registration); set.add(newI); } wr.setIus(set); } else { Log.info("Could not be found: iuses"); } } // lane_workflow_runs if (newWR.getLanes() != null) { SortedSet<Lane> lanes = newWR.getLanes(); if (lanes != null) { SortedSet<Lane> set = new TreeSet<>(); for (Lane lane : lanes) { LaneService ls = BeanFactory.getLaneServiceBean(); Lane newL = ls.findBySWAccession(lane.getSwAccession()); newL.givesPermission(registration); set.add(newL); } wr.setLanes(set); } else { Log.info("Could not be found: lanes"); } } wr.setCommand(newWR.getCommand()); wr.setCurrentWorkingDir(newWR.getCurrentWorkingDir()); wr.setDax(newWR.getDax()); wr.setHost(newWR.getHost()); wr.setIniFile(newWR.getIniFile()); wr.setName(newWR.getName()); wr.setStatus(newWR.getStatus()); wr.setStatusCmd(newWR.getStatusCmd()); wr.setTemplate(newWR.getTemplate()); wr.setSeqwareRevision(newWR.getSeqwareRevision()); wr.setUserName(newWR.getUserName()); wr.setUpdateTimestamp(new Date()); wr.setStdErr(newWR.getStdErr()); wr.setStdOut(newWR.getStdOut()); wr.setWorkflowEngine(newWR.getWorkflowEngine()); if (newWR.getInputFileAccessions() != null) { Log.debug("Saving " + wr.getInputFileAccessions().size() + " input files"); wr.getInputFileAccessions().addAll(newWR.getInputFileAccessions()); } if (newWR.getWorkflow() != null) { WorkflowService ws = BeanFactory.getWorkflowServiceBean(); Workflow w = ws.findByID(newWR.getWorkflow().getWorkflowId()); if (w != null) { wr.setWorkflow(w); } else { Log.info("Could not be found: workflow " + newWR.getWorkflow()); } } if (newWR.getOwner() != null) { Registration reg = BeanFactory.getRegistrationServiceBean().findByEmailAddress(newWR.getOwner().getEmailAddress()); if (reg != null) { wr.setOwner(reg); } else { Log.info("Could not be found: " + newWR.getOwner()); } } else if (wr.getOwner() == null) { wr.setOwner(registration); } if (newWR.getWorkflowRunAttributes() != null) { WorkflowRunIDResource.mergeAttributes(wr.getWorkflowRunAttributes(), newWR.getWorkflowRunAttributes(), wr); } // SEQWARE-1778 - try to properly create parameters in the workflow_run_param table as well // convert ini file parameters into expected format HashMap<String, String> map = new HashMap<>(); if (wr.getIniFile() != null && !wr.getIniFile().isEmpty()) { // just skip if previous ini file params detected if (wr.getWorkflowRunParams().size() > 0) { Log.debug("Skipping since params: " + wr.getWorkflowRunParams().size()); } else { String[] splitByWholeSeparator = StringUtils.splitByWholeSeparator(wr.getIniFile(), "\n"); for (String line : splitByWholeSeparator) { String[] lineSplit = StringUtils.splitByWholeSeparator(line, "="); if (lineSplit.length == 0) { continue; } map.put(lineSplit[0], lineSplit.length > 1 ? lineSplit[1] : ""); } SortedSet<WorkflowRunParam> createWorkflowRunParameters = MapTools.createWorkflowRunParameters(map); // looks like the WorkflowManager code does not set workflow run for (WorkflowRunParam p : createWorkflowRunParameters) { p.setWorkflowRun(wr); } Log.debug("Setting params: " + createWorkflowRunParameters.size()); wr.getWorkflowRunParams().addAll(createWorkflowRunParameters); } } wrs.update(registration, wr); // direct DB calls if (newWR.getIus() != null) { addNewIUSes(newWR, wr); } if (newWR.getLanes() != null) { addNewLanes(newWR, wr); } return wr; } private WorkflowRun getWorkflowRun(WorkflowRunService ss) throws NumberFormatException { WorkflowRun workflowRun = testIfNull(ss.findBySWAccession(getId())); return workflowRun; } /** * {@inheritDoc} * * @return */ @Override public Representation put(Representation entity) { Representation toreturn = null; if (entity.getMediaType().equals(MediaType.APPLICATION_XML)) { WorkflowRun newWR = null; JaxbObject<WorkflowRun> jo = new JaxbObject<>(); try { String text = entity.getText(); Log.debug(text); newWR = (WorkflowRun) XmlTools.unMarshal(jo, new WorkflowRun(), text); } catch (SAXException | IOException ex) { Log.fatal(ex, ex); throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, ex); } try { WorkflowRun wr = updateWorkflowRun(newWR); Hibernate3DtoCopier copier = new Hibernate3DtoCopier(); Document line = XmlTools.marshalToDocument(jo, copier.hibernate2dto(wr)); toreturn = XmlTools.getRepresentation(line); getResponse().setEntity(toreturn); getResponse().setLocationRef(getRequest().getRootRef() + "/workflowruns/" + newWR.getSwAccession()); getResponse().setStatus(Status.SUCCESS_CREATED); } catch (SecurityException e) { getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN, e); } catch (SQLException ex) { Log.fatal(ex, ex); throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, ex); } catch (Exception e) { Log.error(e, e); getResponse().setStatus(Status.SERVER_ERROR_INTERNAL, e); } finally { try { entity.exhaust(); } catch (IOException ex) { Log.fatal(ex, ex); throw new ResourceException(Status.SERVER_ERROR_INTERNAL, ex); } entity.release(); DBAccess.close(); } } else { throw new ResourceException(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE); } return toreturn; } private void addNewIUSes(WorkflowRun wr, WorkflowRun currentWR) throws SQLException, ResourceException { Set<Integer> newIUSswa = new HashSet<>(); for (IUS ius : wr.getIus()) { newIUSswa.add(ius.getSwAccession()); } Set<IUS> iuses = currentWR.getIus(); for (IUS ius : iuses) { int swa = ius.getSwAccession(); newIUSswa.remove(swa); } IUSService is = BeanFactory.getIUSServiceBean(); for (int swa : newIUSswa) { IUS ius = is.findBySWAccession(swa); if (ius != null && ius.givesPermission(registration)) { currentWR.getIus().add(ius); } else if (ius == null) { Log.info("Could not be found: ius " + swa); } } } private void addNewLanes(WorkflowRun wr, WorkflowRun currentWR) throws SQLException, ResourceException { Set<Integer> newLaneSWA = new HashSet<>(); for (Lane lane : wr.getLanes()) { newLaneSWA.add(lane.getSwAccession()); } Set<Lane> lanes = currentWR.getLanes(); for (Lane l : lanes) { int swa = l.getSwAccession(); newLaneSWA.remove(swa); } LaneService ls = BeanFactory.getLaneServiceBean(); for (int swa : newLaneSWA) { Lane l = ls.findBySWAccession(swa); if (l != null && l.givesPermission(registration)) { currentWR.getLanes().add(l); } } } }