Changeset 5740


Ignore:
Timestamp:
Nov 20, 2019, 8:30:18 AM (3 years ago)
Author:
Nicklas Nordborg
Message:

Merged Reggie 4.23.3 to the trunk.

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • extensions/net.sf.basedb.reggie/trunk

  • extensions/net.sf.basedb.reggie/trunk/resources/index.js

    r5683 r5740  
    359359    msg += '<div class="snake-quote-source">Indiana Jones - Raiders of the Lost Ark</div>';
    360360    Forms.showNotification('caseName', msg, 'snake-quote', 'pointer-above');
    361   }
    362 
     361    var url = 'Session.servlet?ID='+App.getSessionId();
     362    url += '&cmd=ReggieTheSnakeWasSummoned';
     363    Wizard.asyncJsonRequest(url);
     364  }
    363365 
    364366  return index;
  • extensions/net.sf.basedb.reggie/trunk/resources/libprep/mrna_protocol.js

    r5552 r5740  
    184184        totalVolume = mrna.DilutionVolume;
    185185      }
    186       else if (totalVolume > mrna.DilutionVolume)
     186      else if (totalVolume - 0.05 > mrna.DilutionVolume) // Use 0.05 to avoid issues with 50.0000000001 > 50.0
    187187      {
    188188        remarks[remarks.length] = 'Large mix; Use '+Reggie.formatNumber(mrna.DilutionVolume, 'µl', 1);
  • extensions/net.sf.basedb.reggie/trunk/resources/libprep/select_rna.js

    r5552 r5740  
    16961696      }
    16971697
    1698       if (info && info.id && info.bioWell && !rna.stratagene)
     1698      if (info && info.id && !rna.stratagene)
    16991699      {
    17001700        rna.usedQuantity = Math.max(Math.min(info.remainingQuantity, rna.qc ? QUANTITY_QC : QUANTITY_REGULAR), QUANTITY_MINIMAL); // µg
     
    17381738        else
    17391739        {
    1740           warningMsg[warningMsg.length] = 'No quantity';
     1740          if (!rna.external) warningMsg[warningMsg.length] = 'No quantity';
    17411741        }
    17421742        if (info.rqs)
     
    17501750          if (info.rin < QUALITY_SCORE_WARNING_LIMIT) warningMsg[warningMsg.length] = 'Low RIN value';
    17511751        }
    1752         else if (!info.preNormalized)
     1752        else if (!info.preNormalized && !rna.external)
    17531753        {
    17541754          warningMsg[warningMsg.length] = 'No RQS/RIN value';
     
    17591759          text += '<div class="volumes"><span class="volume">'+Numbers.formatNumber(volRNA, 1)+'</span> + <span class="water">'+Numbers.formatNumber(water, 1)+'µl</span></div>';
    17601760        }
     1761        else
     1762        {
     1763          if (!rna.external) warningMsg[warningMsg.length] = 'No NDConc value';
     1764        }
     1765        if (info.QiacubeDate)
     1766        {
     1767          text += '<div class="qiacube-date">'+info.QiacubeDate+'</div>';
     1768        }
     1769        else if (info.DilutionDate)
     1770        {
     1771          text += '<div class="dilution-date">'+info.DilutionDate+'</div>';
     1772        }
    17611773        else
    17621774        {
    1763           warningMsg[warningMsg.length] = 'No NDConc value';
    1764         }
    1765         if (info.QiacubeDate)
    1766         {
    1767           text += '<div class="qiacube-date">'+info.QiacubeDate+'</div>';
    1768         }
    1769         else if (info.DilutionDate)
    1770         {
    1771           text += '<div class="dilution-date">'+info.DilutionDate+'</div>';
    1772         }
    1773         else
    1774         {
    1775           warningMsg[warningMsg.length] = info.preNormalized ? 'No DilutionDate value' : 'No QiacubeDate value';
     1775          if (!rna.external) warningMsg[warningMsg.length] = info.preNormalized ? 'No DilutionDate value' : 'No QiacubeDate value';
    17761776        }
    17771777        if (info.AutoProcessing)
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/map-external-data.js

    r5663 r5740  
    3030  {
    3131    var frm = document.forms['reggie'];
    32     var fromPnr = frm.mapFrom.value == 'PersonalNo';
     32    var fromPnr = frm.mapFrom.value == 'PersonalNo' || frm.mapFrom.value == 'PAD';
    3333   
    3434    Doc.showHide('exportPersonalNo', !fromPnr);
     35    Doc.showHide('alsoExportPad', !fromPnr);
    3536    Doc.showHide('exportPatientId', fromPnr);
    3637    Doc.showHide('alsoExportCaseId', fromPnr);
     
    6364        preview += Strings.encodeTags(line) + '\n';
    6465      }
    65       if (mapFrom == null && line.match(/^[QCS]\d+\t.*$/)) // We look for lines starting with 'Q', 'C' or 'S' followed by {digits} and a {tab}
     66      if (mapFrom == null)
    6667      {
    67         var firstChar = line.charAt(0);
    68         if (firstChar == 'Q')
     68        if (line.match(/^[QCS]\d+\t.*$/))// We look for lines starting with 'Q', 'C' or 'S' followed by {digits} and a {tab}
    6969        {
    70           mapFrom = 'PatientId';
     70          var firstChar = line.charAt(0);
     71          if (firstChar == 'Q')
     72          {
     73            mapFrom = 'PatientId';
     74          }
     75          else if (firstChar == 'C')
     76          {
     77            mapFrom = 'CaseId';
     78          }
     79          else if (firstChar == 'S')
     80          {
     81            mapFrom = 'SpecimenId';
     82          }
    7183        }
    72         else if (firstChar == 'C')
     84        else if (lineNo == 0 && line.match(/^[^\t]*pad/i)) // If the first header column contains 'pad' (ignoring case) we assume it contains PAD values
    7385        {
    74           mapFrom = 'CaseId';
    75         }
    76         else if (firstChar == 'S')
    77         {
    78           mapFrom = 'SpecimenId';
     86          mapFrom = 'PAD';
    7987        }
    8088      }
     
    108116    url += '&exportCaseId='+(frm.exportCaseId.checked ? 1 : 0);
    109117    url += '&exportSpecimenId='+(frm.exportSpecimenId.checked ? 1 : 0);
     118    url += '&exportPad='+(frm.exportPad.checked ? 1 : 0);
    110119    url += '&sortOutput='+(frm.sortOutputOrder.checked ? 1 : 0);
    111120    Wizard.showLoadingAnimation('Working...', 'map-data-progress');
  • extensions/net.sf.basedb.reggie/trunk/resources/personal/map-external-data.jsp

    r5663 r5740  
    101101          <select name="mapFrom" id="mapFrom">
    102102            <option value="PersonalNo">Personal number
     103            <option value="PAD">PAD
    103104            <option value="PatientId">Patient release ID
    104105            <option value="CaseId">Case release ID
     
    115116        <td class="input" style="padding-top: 4px; padding-bottom: 4px;">
    116117          <div id="exportPersonalNo" style="display: none;"><input type="checkbox" checked disabled>Personal number</div>
     118          <div id="alsoExportPad" style="display: none;"><label><input type="checkbox" name="exportPad" id="exportPad">PAD</label></div>
    117119          <div id="exportPatientId" style="display: none;"><input type="checkbox" checked disabled>Patient release ID</div>
    118120          <div id="alsoExportCaseId" style="display: none;"><label><input type="checkbox" name="exportCaseId" id="exportCaseId">Case release ID</label></div>
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/activity/ActivityDef.java

    r5728 r5740  
    242242  */
    243243  public static final ActivityDef IMPORTED_RNA_ALIQUOTS = new ActivityDef("imported-rna-aliquots", "Imported 1 aliquot for RNAseq analysis", "Imported {COUNT} aliquots for RNAseq analysis");
    244 
     244 
     245  /**
     246    Reggie the Snake was summoned.
     247  */
     248  public static final ActivityDef REGGIE_THE_SNAKE_WAS_SUMMONED = new ActivityDef("reggie-the-snake-was-summoned", "🐍 Reggie the Snake was summoned", "🐍🐍 Reggie the Snake was summoned {COUNT} times");
    245249 
    246250  private final String id;
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/activity/ActivityEntry.java

    r5421 r5740  
    5050  {
    5151    return LocalDateTime.ofInstant(getEventDate().toInstant(), ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS);
     52  }
     53 
     54  /**
     55    Get the age of the event in seconds.
     56    @since 4.23.3
     57  */
     58  public default int getAgeInSeconds()
     59  {
     60    return (int)((System.currentTimeMillis() - getEventDate().getTime()) / 1000);
    5261  }
    5362 
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/activity/ActivityLog.java

    r5617 r5740  
    394394      int ageInDays = (int)ChronoUnit.DAYS.between(a.getEventDay(), today);
    395395      boolean remove = ageInDays > maxAgeInDays || (ageInDays > 1 && numPassed >= maxEntries);
     396      if (a.getMessage().contains("Reggie the Snake") && a.getAgeInSeconds() > 180)
     397      {
     398        // Reggie the Snake never stays more than 3 minutes
     399        remove = true;
     400      }
    396401      if (!remove) numPassed++;
    397402      return remove;
     
    403408    to the disc at regular intervals.
    404409  */
    405   static class SaveActivityLog
     410  public static class SaveActivityLog
    406411    extends TimerTask
    407412  {
    408     SaveActivityLog()
     413    public SaveActivityLog()
    409414    {}
    410415   
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ExportServlet.java

    r5663 r5740  
    5151import net.sf.basedb.core.Type;
    5252import net.sf.basedb.core.query.Annotations;
    53 import net.sf.basedb.core.query.Expression;
    5453import net.sf.basedb.core.query.Expressions;
    5554import net.sf.basedb.core.query.Hql;
     
    513512  }
    514513
    515   @SuppressWarnings({"unchecked", "rawtypes"})
    516514  @Override
    517515  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
     
    538536       
    539537        String mapFrom = Values.getString(req.getParameter("mapFrom"), "PersonalNo");
    540         String mapFromFriendlyName = "personal number";
    541538        boolean exportCaseId = Values.getBoolean(req.getParameter("exportCaseId"));
    542539        boolean exportSpecimenId = Values.getBoolean(req.getParameter("exportSpecimenId"));
     540        boolean exportPad = Values.getBoolean(req.getParameter("exportPad"));
    543541        boolean sortOutput = Values.getBoolean(req.getParameter("sortOutput"));
    544542
    545543        SnapshotManager manager = new SnapshotManager();
    546         Object[] headerOut = new Object[2];
    547         ValueConverter<BioSource, String>[] dataConvert = new ValueConverter[1];
    548         List<Object[]> dataOut = new ArrayList<>();
    549 
    550         ItemQuery<BioSource> findPat = BioSource.getQuery();
    551         Subtype.PATIENT.addFilter(dc, findPat);
    552         findPat.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     544        List<OutputColumn> outColumns = new ArrayList<>();
     545        PatientLoader loader = null;
     546        if ("PatientId".equals(mapFrom))
     547        {
     548          loader = PatientLoader.fromPatientId(dc);
     549          outColumns.add(new PatientToPersonalNumberConverter(dc, manager));
     550          if (exportPad) outColumns.add(ReleaseIdToPadConverter.fromPatientId(dc, manager));
     551        }
     552        else if ("CaseId".equals(mapFrom))
     553        {
     554          loader = PatientLoader.fromCaseId(dc);
     555          outColumns.add(new PatientToPersonalNumberConverter(dc, manager));
     556          if (exportPad) outColumns.add(ReleaseIdToPadConverter.fromCaseId(dc, manager));
     557        }
     558        else if ("SpecimenId".equals(mapFrom))
     559        {
     560          loader = PatientLoader.fromSpecimenId(dc);
     561          outColumns.add(new PatientToPersonalNumberConverter(dc, manager));
     562          if (exportPad) outColumns.add(ReleaseIdToPadConverter.fromSpecimenId(dc, manager));
     563        }
     564        else if ("PAD".equals(mapFrom))
     565        {
     566          PatientLoaderFromPad padLoader = new PatientLoaderFromPad(dc);
     567          loader = padLoader;
     568          outColumns.add(new PatientToReleaseIdConverter());
     569          if (exportCaseId) outColumns.add(padLoader.toCaseId());
     570          if (exportSpecimenId) outColumns.add(padLoader.toSpecimenId());
     571        }
     572        else // "PersonalNo"
     573        {
     574          loader = PatientLoader.fromPersonalNumber(dc);
     575          outColumns.add(new PatientToReleaseIdConverter());
     576          if (exportCaseId) outColumns.add(new PatientToCaseReleaseIdConverter(dc));
     577          if (exportSpecimenId) outColumns.add(new PatientToSpecimenReleaseIdConverter(dc));
     578        }
    553579       
    554         // Modify the query and output headers depending on the "mapFrom" parameter
    555         // we should be able to execute it with a value from the file and find a patient item
    556         Expression mapFromParameter = Expressions.parameter("mapFrom");
    557         if ("PatientId".equals(mapFrom))
    558         {
    559           mapFromFriendlyName = "patient release ID";
    560           findPat.restrict(Restrictions.eq(Hql.property("externalId"), mapFromParameter));
    561           dataConvert[0] = new PatientToPersonalNumberConverter(dc, manager);
    562           headerOut[0] = "PersonalNumber";
    563         }
    564         else if ("CaseId".equals(mapFrom))
    565         {
    566           mapFromFriendlyName = "case release ID";
    567           findPat.join(Hql.innerJoin("childCreationEvents", "cce"));
    568           findPat.join(Hql.innerJoin("cce", "event", "evt"));
    569           findPat.join(Hql.innerJoin("evt", "bioMaterial", "cse")); // 'cse' should now reference a case
    570           findPat.restrict(Restrictions.eq(Hql.property("cse", "externalId"), mapFromParameter));
    571           dataConvert[0] = new PatientToPersonalNumberConverter(dc, manager);
    572           headerOut[0] = "PersonalNumber";
    573         }
    574         else if ("SpecimenId".equals(mapFrom))
    575         {
    576           mapFromFriendlyName = "specimen release ID";
    577           findPat.join(Hql.innerJoin("childCreationEvents", "cce"));
    578           findPat.join(Hql.innerJoin("cce", "event", "evt"));
    579           findPat.join(Hql.innerJoin("evt", "bioMaterial", "cse")); // 'cse' should now reference a case
    580           findPat.join(Hql.innerJoin("cse", "childCreationEvents", "cce2"));
    581           findPat.join(Hql.innerJoin("cce2", "event", "evt2"));
    582           findPat.join(Hql.innerJoin("evt2", "bioMaterial", "spm")); // 'spm' should now reference a specimen/nospecimen
    583           findPat.restrict(Restrictions.eq(Hql.property("spm", "externalId"), mapFromParameter));
    584           dataConvert[0] = new PatientToPersonalNumberConverter(dc, manager);
    585           headerOut[0] = "PersonalNumber";
    586         }
    587         else // "PersonalNo"
    588         {
    589           findPat.join(Annotations.innerJoin(null, Annotationtype.PERSONAL_NUMBER.load(dc), "pnr"));
    590           findPat.restrict(Restrictions.eq(Hql.alias("pnr"), mapFromParameter));
    591          
    592           int numCols = 2 + (exportCaseId ? 1 : 0) + (exportSpecimenId ? 1 : 0);
    593           if (numCols > headerOut.length) // We need more output columns
    594           {
    595             headerOut = new Object[numCols];
    596             dataConvert = new ValueConverter[numCols-1]; // The last column need to converter
    597           }
    598           int col = 0;
    599           dataConvert[col] = new PatientToReleaseIdConverter();
    600           headerOut[col++] = "PatientId";
    601           if (exportCaseId)
    602           {
    603             headerOut[col] = "CaseId";
    604             dataConvert[col++] = new PatientToCaseReleaseIdConverter(dc);
    605           }
    606           if (exportSpecimenId)
    607           {
    608             headerOut[col] = "SpecimenId";
    609             dataConvert[col++] = new PatientToSpecimenReleaseIdConverter(dc);
    610           }
    611         }
    612580
    613581        InputStream uploadIn = null;
     
    640608          }
    641609       
    642           int lastCol = headerOut.length - 1;
     610          int lastCol = outColumns.size();
     611          Object[] headerOut = new Object[lastCol+1];
     612          for (int colNo = 0; colNo < lastCol; colNo++)
     613          {
     614            headerOut[colNo] = outColumns.get(colNo).getHeader();
     615          }
    643616          headerOut[lastCol] = dataIn[1];
    644617       
    645           int lineIn = 0;
    646618          int lineOut = 0;
    647619          int linesSkipped = 0;
     620          InputLine inputLine = new InputLine();
     621          List<Object[]> dataOut = new ArrayList<>();
    648622         
    649623          String data = uploadReader.readLine();
     
    651625          {
    652626            parsedCharacters += data.length() + 1;
    653             lineIn++;
    654             progress.display((int)(100*parsedCharacters / totalBytes), "Working... " + lineIn + " lines parsed so far...");
     627            inputLine.lineNo++;
     628            progress.display((int)(100*parsedCharacters / totalBytes), "Working... " + inputLine.lineNo + " lines parsed so far...");
    655629           
    656630            dataIn = data.split("\t", 2);
    657631            if (dataIn.length != 2)
    658632            {
    659               throw new IOException("On line " + lineIn + ": The file need at least 2 data columns");
     633              throw new IOException("On line " + inputLine.lineNo + ": The file need at least 2 data columns");
    660634            }
    661635
    662             String fromId = Values.getStringOrNull(dataIn[0]);
    663             if (fromId == null)
     636            inputLine.fromId = Values.getStringOrNull(dataIn[0]);
     637            if (inputLine.fromId == null)
    664638            {
    665               throw new IOException("On line " + lineIn + ": " + mapFromFriendlyName + " is missing");
     639              throw new IOException("On line " + inputLine.lineNo + ": " + loader.getMapFromFriendlyName() + " is missing");
    666640            }
    667  
    668             findPat.setParameter("mapFrom", fromId, Type.STRING);
    669             List<BioSource> patients = findPat.list(dc);
    670             if (patients.size() == 0)
     641           
     642            inputLine.patient = loader.convert(inputLine);
     643 
     644            if (inputLine.patient == null)
    671645            {
    672646              linesSkipped++;
    673647              if (linesSkipped > 100 && lineOut == 0)
    674648              {
    675                 throw new IOException("On line " + lineIn + ": No patients found after " + lineIn + " lines. Is this the correct file?");
     649                throw new IOException("On line " + inputLine.lineNo + ": No patients found after " + inputLine.lineNo + " lines. Is this the correct file?");
    676650              }
    677             }
    678             else if (patients.size() > 1)
    679             {
    680               throw new IOException("On line " + lineIn + ": Found " + patients.size() + " patients with same " + mapFromFriendlyName + ": " + fromId);
    681651            }
    682652            else
    683653            {
    684               BioSource pat = patients.get(0);
    685654              Object[] output = new Object[headerOut.length];
    686               for (int c = 0; c < lastCol; c++)
     655              for (int colNo = 0; colNo < lastCol; colNo++)
    687656              {
    688                 output[c] = dataConvert[c].convert(pat);
     657                output[colNo] = outColumns.get(colNo).convert(inputLine);
    689658              }
    690659              output[lastCol] = dataIn[1];
     
    697666          if (lineOut == 0)
    698667          {
    699             throw new IOException("On line " + lineIn + ": No patients found. Is this the correct file?");
     668            throw new IOException("On line " + inputLine.lineNo + ": No patients found. Is this the correct file?");
    700669          }
    701670
     
    714683          tmpWriter.flush();
    715684          tmpOut.flush();
    716           jsonMessages.add("Parsed " + lineIn + " lines from input file");
     685          jsonMessages.add("Parsed " + inputLine.lineNo + " lines from input file");
    717686          jsonMessages.add("Wrote " + lineOut + " lines to output file");
    718687          if (linesSkipped > 0)
     
    724693            jsonMessages.add("A patient was found for all lines");
    725694          }
    726           json.put("numLinesIn", lineIn);
     695          json.put("numLinesIn", inputLine.lineNo);
    727696          json.put("numLinesOut", lineOut);
    728697          json.put("numNotFound", linesSkipped);
     
    15061475 
    15071476  /**
     1477    Represents a line from the input file.
     1478    TODO -- add more data here ?
     1479  */
     1480  static class InputLine
     1481  {
     1482    int lineNo;
     1483    String fromId;
     1484    BioSource patient;
     1485  }
     1486 
     1487  /**
     1488    Implementations need to take an input line and
     1489    find a single patient for that line.
     1490  */
     1491  static abstract class PatientLoader
     1492    implements ValueConverter<InputLine, BioSource>
     1493  {
     1494    static PatientLoader fromPersonalNumber(DbControl dc)
     1495    {
     1496      ItemQuery<BioSource> query = BioSource.getQuery();
     1497      query.join(Annotations.innerJoin(null, Annotationtype.PERSONAL_NUMBER.load(dc), "pnr"));
     1498      query.restrict(Restrictions.eq(Hql.alias("pnr"), Expressions.parameter("fromId")));
     1499      return new PatientLoaderByQuery(dc, query, "personal number");
     1500    }
     1501   
     1502    static PatientLoader fromPatientId(DbControl dc)
     1503    {
     1504      ItemQuery<BioSource> query = BioSource.getQuery();
     1505      query.restrict(Restrictions.eq(Hql.property("externalId"), Expressions.parameter("fromId")));
     1506      return new PatientLoaderByQuery(dc, query, "patient release ID");
     1507    }
     1508   
     1509    static PatientLoader fromCaseId(DbControl dc)
     1510    {
     1511      ItemQuery<BioSource> query = BioSource.getQuery();
     1512      query.join(Hql.innerJoin("childCreationEvents", "cce"));
     1513      query.join(Hql.innerJoin("cce", "event", "evt"));
     1514      query.join(Hql.innerJoin("evt", "bioMaterial", "cse")); // 'cse' should now reference a case
     1515      query.restrict(Restrictions.eq(Hql.property("cse", "externalId"), Expressions.parameter("fromId")));
     1516      return new PatientLoaderByQuery(dc, query, "case release ID");
     1517    }
     1518   
     1519    static PatientLoader fromSpecimenId(DbControl dc)
     1520    {
     1521      ItemQuery<BioSource> query = BioSource.getQuery();
     1522      query.join(Hql.innerJoin("childCreationEvents", "cce"));
     1523      query.join(Hql.innerJoin("cce", "event", "evt"));
     1524      query.join(Hql.innerJoin("evt", "bioMaterial", "cse")); // 'cse' should now reference a case
     1525      query.join(Hql.innerJoin("cse", "childCreationEvents", "cce2"));
     1526      query.join(Hql.innerJoin("cce2", "event", "evt2"));
     1527      query.join(Hql.innerJoin("evt2", "bioMaterial", "spm")); // 'spm' should now reference a specimen/nospecimen
     1528      query.restrict(Restrictions.eq(Hql.property("spm", "externalId"), Expressions.parameter("fromId")));
     1529      return new PatientLoaderByQuery(dc, query, "specimen release ID");
     1530    }
     1531   
     1532    final String mapFromFriendlyName;
     1533    final DbControl dc;
     1534
     1535    PatientLoader(DbControl dc, String mapFromFriendlyName)
     1536    {
     1537      this.dc = dc;
     1538      this.mapFromFriendlyName = mapFromFriendlyName;
     1539    }
     1540   
     1541    public String getMapFromFriendlyName()
     1542    {
     1543      return mapFromFriendlyName;
     1544    }
     1545  }
     1546 
     1547  /**
     1548    Patient loader implementation that can find the patient by executing a
     1549    query using the source id as a parameter.
     1550  */
     1551  static class PatientLoaderByQuery
     1552    extends PatientLoader
     1553  {
     1554   
     1555    private final ItemQuery<BioSource> patientQuery;
     1556   
     1557    PatientLoaderByQuery(DbControl dc, ItemQuery<BioSource> patientQuery, String mapFromFriendlyName)
     1558    {
     1559      super(dc, mapFromFriendlyName);
     1560      this.patientQuery = patientQuery;
     1561      Subtype.PATIENT.addFilter(dc, patientQuery);
     1562      patientQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     1563    }
     1564   
     1565    @Override
     1566    public BioSource convert(InputLine ctx)
     1567    {
     1568      patientQuery.setParameter("fromId", ctx.fromId, Type.STRING);
     1569      List<BioSource> patients = patientQuery.list(dc);
     1570      if (patients.size() > 1)
     1571      {
     1572        throw new RuntimeException("On line " + ctx.lineNo + ": Found " + patients.size() + " patients with same " + mapFromFriendlyName + ": " + ctx.fromId);
     1573      }
     1574      return patients.size() == 0 ? null : patients.get(0);
     1575    }
     1576  }
     1577 
     1578  /**
     1579    Patient loader implementation when the source value is a PAD value. This implementation
     1580    is used instead of the PatientLoaderByQuery for improved performance when
     1581    output columns for case and/or specimen release ID are required. The implementation
     1582    executes an initial query to find the specimen item(s) with the given PAD and then
     1583    uses the specimen to find other items. This avoids executing the slow query against
     1584    the PAD annotation more than once.
     1585  */
     1586  static class PatientLoaderFromPad
     1587    extends PatientLoader
     1588  {
     1589   
     1590    private final ItemQuery<Sample> specimenQuery;
     1591    private final ItemQuery<BioSource> patientQuery;
     1592    private List<Integer> currentSpecimen;
     1593
     1594    public PatientLoaderFromPad(DbControl dc)
     1595    {
     1596      super(dc, "PAD");
     1597     
     1598      specimenQuery = Sample.getQuery();
     1599      specimenQuery.restrict(
     1600        Restrictions.or(
     1601          Subtype.SPECIMEN.restriction(dc, null),
     1602          Subtype.NO_SPECIMEN.restriction(dc, null)
     1603        ));
     1604      specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     1605      specimenQuery.join(Annotations.innerJoin(null, Annotationtype.PAD.load(dc), "pad"));
     1606      specimenQuery.restrict(Restrictions.eq(Hql.alias("pad"), Expressions.parameter("fromId")));
     1607     
     1608      patientQuery = BioSource.getQuery();
     1609      Subtype.PATIENT.addFilter(dc, patientQuery);
     1610      patientQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     1611      patientQuery.join(Hql.innerJoin("childCreationEvents", "cce"));
     1612      patientQuery.join(Hql.innerJoin("cce", "event", "evt"));
     1613      patientQuery.join(Hql.innerJoin("evt", "bioMaterial", "cse")); // 'cse' should now reference a case
     1614      patientQuery.join(Hql.innerJoin("cse", "childCreationEvents", "cce2"));
     1615      patientQuery.join(Hql.innerJoin("cce2", "event", "evt2"));
     1616      patientQuery.join(Hql.innerJoin("evt2", "bioMaterial", "spm")); // 'spm' should now reference a specimen/nospecimen
     1617      patientQuery.restrict(Restrictions.in(Hql.alias("spm"), Expressions.parameter("specimen")));
     1618      patientQuery.setDistinct(true);
     1619    }
     1620   
     1621    @Override
     1622    public String getMapFromFriendlyName()
     1623    {
     1624      return "PAD";
     1625    }
     1626
     1627    @Override
     1628    public BioSource convert(InputLine ctx)
     1629    {
     1630      specimenQuery.setParameter("fromId", ctx.fromId, Type.STRING);
     1631      currentSpecimen = specimenQuery.idList(dc);
     1632     
     1633      if (currentSpecimen.size() == 0) return null;
     1634     
     1635      patientQuery.setParameter("specimen", currentSpecimen, Type.INT);
     1636      List<BioSource> patients = patientQuery.list(dc);
     1637      if (patients.size() > 1)
     1638      {
     1639        throw new RuntimeException("On line " + ctx.lineNo + ": Found " + patients.size() + " patients with same PAD: " + ctx.fromId);
     1640      }
     1641      return patients.size() == 0 ? null : patients.get(0);
     1642    }
     1643   
     1644    /**
     1645      Create an output implementation for the specimen release id.
     1646    */
     1647    public OutputColumn toSpecimenId()
     1648    {
     1649      ItemQuery<Sample> query = Sample.getQuery();
     1650      query.restrict(Restrictions.in(Hql.property("id"), Expressions.parameter("specimen")));
     1651      return new PadToReleaseIdConverter("SpecimenId", dc, query, this);
     1652    }
     1653   
     1654    /**
     1655      Create an output implementation for the case release id.
     1656    */
     1657    public OutputColumn toCaseId()
     1658    {
     1659      ItemQuery<Sample> query = Sample.getQuery();
     1660      Subtype.CASE.addFilter(dc, query);
     1661      query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     1662      query.join(Hql.innerJoin("childCreationEvents", "cce"));
     1663      query.join(Hql.innerJoin("cce", "event", "evt"));
     1664      query.join(Hql.innerJoin("evt", "bioMaterial", "spm")); // 'spm' should now reference a specimen/nospecimen
     1665      query.restrict(Restrictions.in(Hql.alias("spm"), Expressions.parameter("specimen")));
     1666      return new PadToReleaseIdConverter("CaseId", dc, query, this);
     1667    }
     1668  }
     1669 
     1670 
     1671  /**
     1672    Implementation need to generate an output column
     1673    for a given line.
     1674  */
     1675  static abstract class OutputColumn
     1676    implements ValueConverter<InputLine, String>
     1677  {
     1678   
     1679    private final String header;
     1680    OutputColumn(String header)
     1681    {
     1682      this.header = header;
     1683    }
     1684   
     1685    public String getHeader()
     1686    {
     1687      return header;
     1688    }
     1689  }
     1690 
     1691  /**
    15081692    Get the external (release) ID from the patient.
    15091693  */
    15101694  static class PatientToReleaseIdConverter
    1511     implements ValueConverter<BioSource, String>
     1695    extends OutputColumn
    15121696  {
    15131697    PatientToReleaseIdConverter()
    1514     {}
    1515 
    1516     @Override
    1517     public String convert(BioSource patient)
    1518     {
    1519       return patient.getExternalId();
     1698    {
     1699      super("PatientId");
     1700    }
     1701
     1702    @Override
     1703    public String convert(InputLine ctx)
     1704    {
     1705      return ctx.patient.getExternalId();
    15201706    }
    15211707  }
     
    15261712  */
    15271713  static class PatientToCaseReleaseIdConverter
    1528     implements ValueConverter<BioSource, String>
     1714    extends OutputColumn
    15291715  {
    15301716    private final DbControl dc;
     
    15341720    PatientToCaseReleaseIdConverter(DbControl dc)
    15351721    {
     1722      super("CaseId");
    15361723      this.dc = dc;
    15371724      this.toRelaseId = new ToReleaseIdFormatter();
     
    15451732 
    15461733    @Override
    1547     public String convert(BioSource patient)
    1548     {
    1549       caseQuery.setEntityParameter("pat", patient);
     1734    public String convert(InputLine ctx)
     1735    {
     1736      caseQuery.setEntityParameter("pat", ctx.patient);
    15501737      List<Sample> cases = caseQuery.list(dc);
    15511738      return Values.getString(cases, ",", true, toRelaseId);
     
    15581745  */
    15591746  static class PatientToSpecimenReleaseIdConverter
    1560     implements ValueConverter<BioSource, String>
     1747    extends OutputColumn
    15611748  {
    15621749    private final DbControl dc;
     
    15661753    PatientToSpecimenReleaseIdConverter(DbControl dc)
    15671754    {
     1755      super("SpecimenId");
    15681756      this.dc = dc;
    15691757      this.toRelaseId = new ToReleaseIdFormatter();
     
    15821770 
    15831771    @Override
    1584     public String convert(BioSource patient)
    1585     {
    1586       specimenQuery.setEntityParameter("pat", patient);
     1772    public String convert(InputLine ctx)
     1773    {
     1774      specimenQuery.setEntityParameter("pat", ctx.patient);
    15871775      List<Sample> specimen = specimenQuery.list(dc);
    15881776      return Values.getString(specimen, ",", true, toRelaseId);
     
    15941782  */
    15951783  static class PatientToPersonalNumberConverter
    1596     implements ValueConverter<BioSource, String>
     1784    extends OutputColumn
    15971785  {
    15981786   
     
    16021790    PatientToPersonalNumberConverter(DbControl dc, SnapshotManager manager)
    16031791    {
     1792      super("PersonalNumber");
    16041793      this.dc = dc;
    16051794      this.manager = manager;
     
    16071796 
    16081797    @Override
    1609     public String convert(BioSource patient)
    1610     {
    1611       return (String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, manager, patient);
    1612     }
     1798    public String convert(InputLine ctx)
     1799    {
     1800      return (String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, manager, ctx.patient);
     1801    }
     1802  }
     1803 
     1804  /**
     1805    Maps a release id from patient, case or specimen to PAD
     1806    (one or more) on specimen items. Use one of the factor methods
     1807    to get an instance for the proper release id type.
     1808  */
     1809  static class ReleaseIdToPadConverter
     1810    extends OutputColumn
     1811  {
     1812    private final DbControl dc;
     1813    private final SnapshotManager manager;
     1814    private final ItemQuery<Sample> specimenQuery;
     1815   
     1816    /**
     1817      Get the PAD when the source id is a specimen release id.
     1818    */
     1819    static ReleaseIdToPadConverter fromSpecimenId(DbControl dc, SnapshotManager manager)
     1820    {
     1821      ItemQuery<Sample> query = Sample.getQuery();
     1822      query.restrict(Restrictions.eq(Hql.property("externalId"), Expressions.parameter("fromId")));
     1823      return new ReleaseIdToPadConverter(dc, manager, query);
     1824    }
     1825   
     1826    /**
     1827      Get the PAD(s) when the source id is a case release id.
     1828    */
     1829    static ReleaseIdToPadConverter fromCaseId(DbControl dc, SnapshotManager manager)
     1830    {
     1831      ItemQuery<Sample> query = Sample.getQuery();
     1832      query.join(Hql.innerJoin("parent", "cse"));
     1833      query.restrict(Restrictions.eq(Hql.property("cse", "externalId"), Expressions.parameter("fromId")));
     1834      return new ReleaseIdToPadConverter(dc, manager, query);
     1835    }
     1836   
     1837    /**
     1838      Get the PAD(s) when the source id is a patient release id.
     1839    */
     1840    static ReleaseIdToPadConverter fromPatientId(DbControl dc, SnapshotManager manager)
     1841    {
     1842      ItemQuery<Sample> query = Sample.getQuery();
     1843      query.join(Hql.innerJoin("parent", "cse"));
     1844      query.join(Hql.innerJoin("cse", "parent", "pat"));
     1845      query.restrict(Restrictions.eq(Hql.property("pat", "externalId"), Expressions.parameter("fromId")));
     1846      return new ReleaseIdToPadConverter(dc, manager, query);
     1847    }
     1848   
     1849    private ReleaseIdToPadConverter(DbControl dc, SnapshotManager manager, ItemQuery<Sample> specimenQuery)
     1850    {
     1851      super("PAD");
     1852      this.dc = dc;
     1853      this.manager = manager;
     1854      this.specimenQuery = specimenQuery;
     1855      specimenQuery.restrict(
     1856        Restrictions.or(
     1857          Subtype.SPECIMEN.restriction(dc, null),
     1858          Subtype.NO_SPECIMEN.restriction(dc, null)
     1859        ));
     1860      specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     1861    }
     1862 
     1863    @Override
     1864    public String convert(InputLine ctx)
     1865    {
     1866      specimenQuery.setParameter("fromId", ctx.fromId, Type.STRING);
     1867      List<Sample> specimen = specimenQuery.list(dc);
     1868      String pad = null;
     1869      if (specimen.size() > 1)
     1870      {
     1871        Set<String> allPad = new TreeSet<>();
     1872        for (Sample s : specimen)
     1873        {
     1874          allPad.add((String)Annotationtype.PAD.getAnnotationValue(dc, manager, s));
     1875        }
     1876        pad = Values.getString(allPad, ",", true);
     1877      }
     1878      else if (specimen.size() == 1)
     1879      {
     1880        pad = (String)Annotationtype.PAD.getAnnotationValue(dc, manager, specimen.get(0));
     1881      }
     1882      return pad;
     1883    }
     1884   
     1885  }
     1886 
     1887  /**
     1888    Output release id for case or specimen items that has been previously found by the
     1889    PatientLoaderFromPad implementation.
     1890  */
     1891  static class PadToReleaseIdConverter
     1892    extends OutputColumn
     1893  {
     1894   
     1895   
     1896    private final DbControl dc;
     1897    private final ItemQuery<Sample> query;
     1898    private final PatientLoaderFromPad padLoader;
     1899   
     1900    private PadToReleaseIdConverter(String header, DbControl dc, ItemQuery<Sample> query, PatientLoaderFromPad padLoader)
     1901    {
     1902      super(header);
     1903      this.dc = dc;
     1904      this.query = query;
     1905      this.padLoader = padLoader;
     1906    }
     1907   
     1908    @Override
     1909    public String convert(InputLine ctx)
     1910    {
     1911      if (padLoader.currentSpecimen.size() == 0) return null;
     1912     
     1913      query.setParameter("specimen", padLoader.currentSpecimen, Type.INT);
     1914      List<Sample> items = query.list(dc);
     1915      String idValues = null;
     1916      if (items.size() > 1)
     1917      {
     1918        Set<String> allId = new TreeSet<>();
     1919        for (Sample s : items)
     1920        {
     1921          allId.add(s.getExternalId());
     1922        }
     1923        idValues = Values.getString(allId, ",", true);
     1924      }
     1925      else if (items.size() == 1)
     1926      {
     1927        idValues = items.get(0).getExternalId();
     1928      }
     1929      return idValues;
     1930    }
     1931
    16131932  }
    16141933 
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/SessionServlet.java

    r5404 r5740  
    1717import org.json.simple.JSONObject;
    1818
     19import net.sf.basedb.core.Application;
    1920import net.sf.basedb.core.DbControl;
    2021import net.sf.basedb.core.Directory;
     
    2526import net.sf.basedb.reggie.JsonUtil;
    2627import net.sf.basedb.reggie.Reggie;
     28import net.sf.basedb.reggie.activity.ActivityDef;
    2729import net.sf.basedb.reggie.activity.ActivityEntry;
    2830import net.sf.basedb.reggie.activity.ActivityLog;
     
    206208        }
    207209      }
     210      else if ("ReggieTheSnakeWasSummoned".equals(cmd))
     211      {
     212        sc = Reggie.getSessionControl(req);
     213        dc = sc.newDbControl();
     214        ActivityDef.REGGIE_THE_SNAKE_WAS_SUMMONED.merge(dc, 1).setUser("Indiana Jones");
     215        dc.commit();
     216        // Makes Reggie the Snake go away after at least 200 seconds
     217        Application.getScheduler().schedule(new ActivityLog.SaveActivityLog(), 200000, true);
     218      }
    208219     
    209220    }
Note: See TracChangeset for help on using the changeset viewer.