uk.ac.bbsrc.tgac.miso.spring.ajax.PoolControllerHelperService.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.bbsrc.tgac.miso.spring.ajax.PoolControllerHelperService.java

Source

/*
 * 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.User;
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.apache.commons.codec.binary.Base64;
import org.krysalis.barcode4j.BarcodeDimension;
import org.krysalis.barcode4j.BarcodeGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import uk.ac.bbsrc.tgac.miso.core.data.*;
import uk.ac.bbsrc.tgac.miso.core.data.impl.LibraryDilution;
import uk.ac.bbsrc.tgac.miso.core.data.impl.emPCRDilution;
import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType;
import uk.ac.bbsrc.tgac.miso.core.data.type.QcType;
import uk.ac.bbsrc.tgac.miso.core.exception.MalformedExperimentException;
import uk.ac.bbsrc.tgac.miso.core.exception.MisoPrintException;
import uk.ac.bbsrc.tgac.miso.core.factory.DataObjectFactory;
import uk.ac.bbsrc.tgac.miso.core.factory.barcode.BarcodeFactory;
import uk.ac.bbsrc.tgac.miso.core.manager.MisoFilesManager;
import uk.ac.bbsrc.tgac.miso.core.manager.PrintManager;
import uk.ac.bbsrc.tgac.miso.core.manager.RequestManager;
import uk.ac.bbsrc.tgac.miso.core.service.printing.MisoPrintService;
import uk.ac.bbsrc.tgac.miso.core.service.printing.context.PrintContext;
import uk.ac.bbsrc.tgac.miso.core.util.LimsUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
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 PoolControllerHelperService {
    protected static final Logger log = LoggerFactory.getLogger(PoolControllerHelperService.class);
    @Autowired
    private SecurityManager securityManager;
    @Autowired
    private RequestManager requestManager;
    @Autowired
    private DataObjectFactory dataObjectFactory;
    @Autowired
    private MisoFilesManager misoFileManager;
    @Autowired
    private BarcodeFactory barcodeFactory;
    @Autowired
    private PrintManager<MisoPrintService, Queue<?>> printManager;

    public JSONObject getPoolQcTypes(HttpSession session, JSONObject json) {
        try {
            StringBuilder sb = new StringBuilder();
            Collection<QcType> types = requestManager.listAllPoolQcTypes();
            for (QcType s : types) {
                sb.append("<option units='" + s.getUnits() + "' value='" + s.getQcTypeId() + "'>" + s.getName()
                        + "</option>");
            }
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("types", sb.toString());
            return JSONUtils.JSONObjectResponse(map);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return JSONUtils.SimpleJSONError("Cannot list all Pool QC Types");
    }

    public JSONObject addPoolQC(HttpSession session, JSONObject json) {
        try {
            for (Object key : json.keySet()) {
                if (json.get(key) == null || json.get(key).equals("")) {
                    String k = (String) key;
                    return JSONUtils.SimpleJSONError("Please enter a value for '" + k + "'");
                }
            }
            if (json.has("poolId") && !json.get("poolId").equals("")) {
                Long poolId = Long.parseLong(json.getString("poolId"));
                Pool<? extends Poolable> pool = requestManager.getPoolById(poolId);
                PoolQC newQc = dataObjectFactory.getPoolQC();
                if (json.has("qcPassed") && json.getString("qcPassed").equals("true")) {
                    pool.setQcPassed(true);
                }
                newQc.setQcCreator(json.getString("qcCreator"));
                newQc.setQcDate(new SimpleDateFormat("dd/MM/yyyy").parse(json.getString("qcDate")));
                newQc.setQcType(requestManager.getPoolQcTypeById(json.getLong("qcType")));
                newQc.setResults(Double.parseDouble(json.getString("results")));
                pool.addQc(newQc);
                requestManager.savePoolQC(newQc);

                StringBuilder sb = new StringBuilder();
                sb.append("<tr><th>QCed By</th><th>QC Date</th><th>Method</th><th>Results</th></tr>");
                for (PoolQC qc : pool.getPoolQCs()) {
                    sb.append("<tr>");
                    sb.append("<td>" + qc.getQcCreator() + "</td>");
                    sb.append("<td>" + qc.getQcDate() + "</td>");
                    sb.append("<td>" + qc.getQcType().getName() + "</td>");
                    sb.append("<td>" + qc.getResults() + " " + qc.getQcType().getUnits() + "</td>");
                    sb.append("</tr>");
                }
                return JSONUtils.SimpleJSONResponse(sb.toString());
            } else {
                return JSONUtils.SimpleJSONError("Cannot detect parent pool ID. Cannot add PoolQC");
            }
        } catch (Exception e) {
            log.error("Failed to add Pool QC to this Pool: ", e);
            return JSONUtils.SimpleJSONError("Failed to add Pool QC to this Pool: " + e.getMessage());
        }
    }

    public JSONObject bulkAddPoolQCs(HttpSession session, JSONObject json) {
        try {
            JSONArray qcs = JSONArray.fromObject(json.getString("qcs"));
            //validate
            boolean ok = true;
            for (JSONObject qc : (Iterable<JSONObject>) qcs) {
                String qcPassed = qc.getString("qcPassed");
                String qcType = qc.getString("qcType");
                String results = qc.getString("results");
                String qcCreator = qc.getString("qcCreator");
                String qcDate = qc.getString("qcDate");

                if (qcPassed == null || qcPassed.equals("") || qcType == null || qcType.equals("")
                        || results == null || results.equals("") || qcCreator == null || qcCreator.equals("")
                        || qcDate == null || qcDate.equals("")) {
                    ok = false;
                }
            }

            //persist
            if (ok) {
                Map<String, Object> map = new HashMap<String, Object>();
                JSONArray a = new JSONArray();
                for (JSONObject qc : (Iterable<JSONObject>) qcs) {
                    JSONObject j = addPoolQC(session, qc);
                    j.put("poolId", qc.getString("poolId"));
                    a.add(j);
                }
                map.put("saved", a);
                return JSONUtils.JSONObjectResponse(map);
            } else {
                log.error(
                        "Failed to add Pool QC to this Pool: one of the required fields of the selected QCs is missing or invalid");
                return JSONUtils.SimpleJSONError(
                        "Failed to add Pool QC to this Pool: one of the required fields of the selected QCs is missing or invalid");
            }
        } catch (Exception e) {
            log.error("Failed to add Pool QC to this Pool: ", e);
            return JSONUtils.SimpleJSONError("Failed to add Pool QC to this Pool: " + e.getMessage());
        }
    }

    public JSONObject changePoolQCRow(HttpSession session, JSONObject json) {
        try {
            JSONObject response = new JSONObject();
            Long qcId = Long.parseLong(json.getString("qcId"));
            PoolQC poolQc = requestManager.getPoolQCById(qcId);
            response.put("results", "<input type='text' id='" + qcId + "' value='" + poolQc.getResults() + "'/>");
            response.put("edit",
                    "<a href='javascript:void(0);' onclick='Pool.qc.editPoolQC(\"" + qcId + "\");'>Save</a>");
            return response;
        } catch (Exception e) {
            log.error("Failed to display Pool QC of this sample: ", e);
            return JSONUtils.SimpleJSONError("Failed to display Pool QC of this sample: " + e.getMessage());
        }
    }

    public JSONObject editPoolQC(HttpSession session, JSONObject json) {
        try {
            if (json.has("qcId") && !json.get("qcId").equals("")) {
                Long qcId = Long.parseLong(json.getString("qcId"));
                PoolQC poolQc = requestManager.getPoolQCById(qcId);
                poolQc.setResults(Double.parseDouble(json.getString("result")));
                requestManager.savePoolQC(poolQc);
                return JSONUtils.SimpleJSONResponse("OK");
            }
        } catch (Exception e) {
            log.error("Failed to add Pool QC to this sample: ", e);
            return JSONUtils.SimpleJSONError("Failed to add Pool QC to this sample: " + e.getMessage());
        }
        return JSONUtils.SimpleJSONError("Cannot add PoolQC");
    }

    private String processDilutions(Set<String> codes) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("<div id='dilslist' class='checklist' style='width: 100%;'>");
        for (String s : codes) {
            if (LimsUtils.isBase64String(s)) {
                //Base64-encoded string, most likely a barcode image beeped in. decode and search
                s = new String(Base64.decodeBase64(s));
            }
            Dilution ed = requestManager.getDilutionByBarcode(s);
            if (ed != null) {
                sb.append("<span>");
                sb.append("<input type='checkbox' value='" + s + "' name='importdilslist' id='importdilslist_"
                        + ed.getName() + "'/>");
                sb.append("<label for='importdilslist_" + ed.getName() + "'>" + ed.getName() + " (" + s
                        + ")</label>");
                sb.append("</span>");
            }
        }
        sb.append("</div>");
        sb.append(
                "<a onclick='Utils.ui.checkAll(\"importdilslist\"); return false;' href='javascript:void(0);'>All</a> "
                        + "/ <a onclick='Utils.ui.uncheckAll(\"importdilslist\"); return false;' href='javascript:void(0);'>None</a>");
        sb.append("<br/><button type='submit' class='br-button ui-state-default ui-corner-all'>Use</button>");
        return sb.toString();
    }

    @Deprecated
    private String processLibraryDilutions(Set<String> codes) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("<div id='dilslist' class='checklist' style='width: 100%;'>");
        for (String s : codes) {
            if (LimsUtils.isBase64String(s)) {
                //Base64-encoded string, most likely a barcode image beeped in. decode and search
                s = new String(Base64.decodeBase64(s));
            }
            LibraryDilution ed = requestManager.getLibraryDilutionByBarcode(s);
            if (ed != null) {
                sb.append("<span>");
                sb.append("<input type='checkbox' value='" + s + "' name='importdilslist' id='importdilslist_"
                        + ed.getName() + "'/>");
                sb.append("<label for='importdilslist_" + ed.getName() + "'>" + ed.getName() + " (" + s
                        + ")</label>");
                sb.append("</span>");
            }
        }
        sb.append("</div>");
        sb.append(
                "<a onclick='Utils.ui.checkAll(\"importdilslist\"); return false;' href='javascript:void(0);'>All</a> "
                        + "/ <a onclick='Utils.ui.uncheckAll(\"importdilslist\"); return false;' href='javascript:void(0);'>None</a>");
        sb.append("<br/><button type='submit' class='br-button ui-state-default ui-corner-all'>Use</button>");
        return sb.toString();
    }

    @Deprecated
    private String processEmPcrDilutions(Set<String> codes) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("<div id='dilslist' class='checklist' style='width: 100%;'>");
        for (String s : codes) {
            if (LimsUtils.isBase64String(s)) {
                //Base64-encoded string, most likely a barcode image beeped in. decode and search
                s = new String(Base64.decodeBase64(s));
            }
            emPCRDilution ed = requestManager.getEmPcrDilutionByBarcode(s);
            if (ed != null) {
                sb.append("<span>");
                sb.append("<input type='checkbox' value='" + s + "' name='importdilslist' id='importdilslist_"
                        + ed.getName() + "'/>");
                sb.append("<label for='importdilslist_" + ed.getName() + "'>" + ed.getName() + " (" + s
                        + ")</label>");
                sb.append("</span>");
            }
        }
        sb.append("</div>");
        sb.append(
                "<a onclick='Utils.ui.checkAll(\"importdilslist\"); return false;' href='javascript:void(0);'>All</a> "
                        + "/ <a onclick='Utils.ui.uncheckAll(\"importdilslist\"); return false;' href='javascript:void(0);'>None</a>");
        sb.append("<br/><button type='submit' class='br-button ui-state-default ui-corner-all'>Use</button>");
        return sb.toString();
    }

    @Deprecated
    public JSONObject selectLibraryDilutionsByBarcodeList(HttpSession session, JSONObject json) {
        try {
            if (json.has("barcodes")) {
                String barcodes = json.getString("barcodes");
                String[] codes = barcodes.split("\n");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList(codes));

                StringBuilder sb = new StringBuilder();
                sb.append("<form action='/miso/pool/illumina/import' method='post'>");
                sb.append("<div style='width: 100%;'>");
                sb.append(processLibraryDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");
                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    public JSONObject selectDilutionsByBarcodeFile(HttpSession session, JSONObject json) {
        try {
            JSONObject barcodes = (JSONObject) session.getAttribute("barcodes");
            log.debug(barcodes.toString());
            if (barcodes.has("barcodes")) {
                JSONArray a = barcodes.getJSONArray("barcodes");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList((String[]) a.toArray(new String[0])));

                StringBuilder sb = new StringBuilder();
                sb.append("<form action='/miso/pool/import' method='post'>");
                sb.append("<div style='width: 100%;'>");
                sb.append(processDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");
                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    public JSONObject selectDilutionsByBarcodeList(HttpSession session, JSONObject json) {
        try {
            if (json.has("barcodes")) {
                String barcodes = json.getString("barcodes");
                String[] codes = barcodes.split("\n");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset        
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList(codes));

                StringBuilder sb = new StringBuilder();
                sb.append("<form action='/miso/pool/import' method='post'>");
                sb.append("<div style='width: 100%;'>");
                sb.append(processDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");
                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    @Deprecated
    public JSONObject selectLibraryDilutionsByBarcodeFile(HttpSession session, JSONObject json) {
        try {
            JSONObject barcodes = (JSONObject) session.getAttribute("barcodes");
            log.debug(barcodes.toString());
            if (barcodes.has("barcodes")) {
                JSONArray a = barcodes.getJSONArray("barcodes");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList((String[]) a.toArray(new String[0])));

                StringBuilder sb = new StringBuilder();
                sb.append("<form action='/miso/pool/import' method='post'>");
                sb.append("<div style='width: 100%;'>");
                sb.append(processLibraryDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");
                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    @Deprecated
    public JSONObject select454EmPCRDilutionsByBarcodeList(HttpSession session, JSONObject json) {
        try {
            if (json.has("barcodes")) {
                String barcodes = json.getString("barcodes");
                String[] codes = barcodes.split("\n");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList(codes));

                StringBuilder sb = new StringBuilder();
                sb.append("<div style='width: 100%;'>");
                sb.append("<form action='/miso/pool/ls454/import' method='post'>");
                sb.append(processEmPcrDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");

                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    @Deprecated
    public JSONObject select454EmPCRDilutionsByBarcodeFile(HttpSession session, JSONObject json) {
        try {
            JSONObject barcodes = (JSONObject) session.getAttribute("barcodes");
            log.debug(barcodes.toString());
            if (barcodes.has("barcodes")) {
                JSONArray a = barcodes.getJSONArray("barcodes");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList((String[]) a.toArray(new String[0])));

                StringBuilder sb = new StringBuilder();
                sb.append("<div style='width: 100%;'>");
                sb.append("<form action='/miso/pool/ls454/import' method='post'>");
                sb.append(processEmPcrDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");

                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    @Deprecated
    public JSONObject selectSolidEmPCRDilutionsByBarcodeList(HttpSession session, JSONObject json) {
        try {
            if (json.has("barcodes")) {
                String barcodes = json.getString("barcodes");
                String[] codes = barcodes.split("\n");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList(codes));

                StringBuilder sb = new StringBuilder();
                sb.append("<div style='width: 100%;'>");
                sb.append("<form action='/miso/pool/solid/import' method='post'>");
                sb.append(processEmPcrDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");

                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    @Deprecated
    public JSONObject selectSolidEmPCRDilutionsByBarcodeFile(HttpSession session, JSONObject json) {
        try {
            JSONObject barcodes = (JSONObject) session.getAttribute("barcodes");
            log.debug(barcodes.toString());
            if (barcodes.has("barcodes")) {
                JSONArray a = barcodes.getJSONArray("barcodes");

                // make sure there are no duplicates and order the strings
                // by putitng the codes in a treeset
                TreeSet<String> hcodes = new TreeSet<String>();
                hcodes.addAll(Arrays.asList((String[]) a.toArray(new String[0])));

                StringBuilder sb = new StringBuilder();
                sb.append("<div style='width: 100%;'>");
                sb.append("<form action='/miso/pool/solid/import' method='post'>");
                sb.append(processEmPcrDilutions(hcodes));
                sb.append("</form>");
                sb.append("</div>");

                session.removeAttribute("barcodes");

                return JSONUtils.SimpleJSONResponse(sb.toString());
            }
        } catch (Exception e) {
            log.debug("Failed to generate barcode selection: ", e);
            return JSONUtils.SimpleJSONError("Failed to generate barcode selection");
        }
        return JSONUtils.SimpleJSONError("Cannot select barcodes");
    }

    public JSONObject getPoolBarcode(HttpSession session, JSONObject json) {
        Long poolId = json.getLong("poolId");
        File temploc = new File(session.getServletContext().getRealPath("/") + "temp/");
        try {
            Pool pool = requestManager.getPoolById(poolId);
            barcodeFactory.setPointPixels(1.5f);
            barcodeFactory.setBitmapResolution(600);

            RenderedImage bi = null;

            if (json.has("barcodeGenerator")) {
                BarcodeDimension dim = new BarcodeDimension(100, 100);
                if (json.has("dimensionWidth") && json.has("dimensionHeight")) {
                    dim = new BarcodeDimension(json.getDouble("dimensionWidth"), json.getDouble("dimensionHeight"));
                }
                BarcodeGenerator bg = BarcodeFactory.lookupGenerator(json.getString("barcodeGenerator"));
                if (bg != null) {
                    bi = barcodeFactory.generateBarcode(pool, bg, dim);
                } else {
                    return JSONUtils.SimpleJSONError(
                            "'" + json.getString("barcodeGenerator") + "' is not a valid barcode generator type");
                }
            } else {
                bi = barcodeFactory.generateSquareDataMatrix(pool, 400);
            }

            if (bi != null) {
                File tempimage = misoFileManager.generateTemporaryFile("barcode-", ".png", temploc);
                if (ImageIO.write(bi, "png", tempimage)) {
                    return JSONUtils.JSONObjectResponse("img", tempimage.getName());
                }
                return JSONUtils.SimpleJSONError("Writing temp image file failed.");
            } else {
                return JSONUtils.SimpleJSONError("Pool has no parseable barcode");
            }
        } catch (IOException e) {
            e.printStackTrace();
            return JSONUtils
                    .SimpleJSONError(e.getMessage() + ": Cannot seem to access " + temploc.getAbsolutePath());
        }
    }

    public JSONObject printPoolBarcodes(HttpSession session, JSONObject json) {
        try {
            User user = securityManager
                    .getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName());
            JSONArray ss = JSONArray.fromObject(json.getString("pools"));

            String serviceName = null;
            if (json.has("serviceName")) {
                serviceName = json.getString("serviceName");
            }

            MisoPrintService<File, Barcodable, PrintContext<File>> mps = null;
            if (serviceName == null) {
                Collection<MisoPrintService> services = printManager
                        .listPrintServicesByBarcodeableClass(Pool.class);
                if (services.size() == 1) {
                    mps = services.iterator().next();
                } else {
                    return JSONUtils.SimpleJSONError(
                            "No serviceName specified, but more than one available service able to print this barcode type.");
                }
            } else {
                mps = printManager.getPrintService(serviceName);
            }

            Queue<File> thingsToPrint = new LinkedList<File>();
            for (JSONObject p : (Iterable<JSONObject>) ss) {
                try {
                    Long poolId = p.getLong("poolId");
                    Pool pool = requestManager.getPoolById(poolId);

                    File f = mps.getLabelFor(pool);
                    if (f != null)
                        thingsToPrint.add(f);
                } catch (IOException e) {
                    e.printStackTrace();
                    return JSONUtils.SimpleJSONError("Error printing pool barcode: " + e.getMessage());
                }
            }

            PrintJob pj = printManager.print(thingsToPrint, mps.getName(), user);
            return JSONUtils.SimpleJSONResponse("Job " + pj.getJobId() + " : Barcodes printed.");
        } catch (MisoPrintException e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError("No printer of that name available: " + e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError("Cannot print barcodes: " + e.getMessage());
        }
    }

    public JSONObject poolSearchExperiments(HttpSession session, JSONObject json) {
        String searchStr = json.getString("str");
        String platformType = json.getString("platform").toUpperCase();
        try {
            if (searchStr.length() > 1) {
                String str = searchStr.toLowerCase();
                StringBuilder b = new StringBuilder();
                List<Experiment> experiments = new ArrayList<Experiment>(requestManager.listAllExperiments());
                int numMatches = 0;
                for (Experiment e : experiments) {
                    if (e.getPlatform().getPlatformType().equals(PlatformType.valueOf(platformType))) {
                        String expName = e.getName() == null ? null : e.getName();
                        if (expName != null
                                && (expName.toLowerCase().equals(str) || expName.toLowerCase().contains(str))
                                || (e.getStudy().getAlias().toLowerCase().contains(str)
                                        || e.getStudy().getName().toLowerCase().contains(str))
                                || (e.getStudy().getProject().getAlias().toLowerCase().contains(str)
                                        || e.getStudy().getProject().getName().toLowerCase().contains(str))) {
                            b.append(
                                    "<div onmouseover=\"this.className='autocompleteboxhighlight'\" onmouseout=\"this.className='autocompletebox'\" class=\"autocompletebox\""
                                            + " onclick=\"Pool.search.poolSearchSelectExperiment('" + e.getId()
                                            + "', '" + e.getName() + "')\">" + "<b>Experiment:</b> " + expName
                                            + "<br/>" + "<b>Description:</b> " + e.getDescription() + "<br/>"
                                            + "<b>Project:</b> " + e.getStudy().getProject().getAlias() + "<br/>"
                                            + "</div>");
                            numMatches++;
                        }
                    }
                }
                if (numMatches == 0) {
                    return JSONUtils.JSONObjectResponse("html", "No matches");
                } else {
                    return JSONUtils.JSONObjectResponse("html",
                            "<div class=\"autocomplete\"><ul>" + b.toString() + "</ul></div>");
                }
            } else {
                return JSONUtils.JSONObjectResponse("html", "Need a longer search pattern ...");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    @Deprecated
    public JSONObject poolSearchDilution(HttpSession session, JSONObject json) {
        String searchStr = json.getString("str");
        String platformType = json.getString("platform").toUpperCase();
        try {
            if (searchStr.length() > 1) {
                if (LimsUtils.isBase64String(searchStr)) {
                    //Base64-encoded string, most likely a barcode image beeped in. decode and search
                    searchStr = new String(Base64.decodeBase64(searchStr));
                }

                //String str = searchStr.toLowerCase();
                StringBuilder b = new StringBuilder();
                List<? extends Dilution> dilutions = new ArrayList<Dilution>(
                        requestManager.listDilutionsBySearch(searchStr, PlatformType.valueOf(platformType)));
                int numMatches = 0;
                for (Dilution d : dilutions) {
                    b.append(
                            "<div onmouseover=\"this.className='autocompleteboxhighlight'\" onmouseout=\"this.className='autocompletebox'\" class=\"autocompletebox\""
                                    + " onclick=\"Pool.search.poolSearchSelectDilution('" + d.getId() + "', '"
                                    + d.getName() + "')\">" + "<b>Dilution: " + d.getName() + "</b><br/>"
                                    + "<b>Library: " + d.getLibrary().getAlias() + "</b><br/>" + "<b>Sample: "
                                    + d.getLibrary().getSample().getAlias() + "</b><br/>" + "</div>");
                    numMatches++;
                }
                if (numMatches == 0) {
                    return JSONUtils.JSONObjectResponse("html", "No matches");
                } else {
                    return JSONUtils.JSONObjectResponse("html",
                            "<div class=\"autocomplete\"><ul>" + b.toString() + "</ul></div>");
                }
            } else {
                return JSONUtils.JSONObjectResponse("html", "Need a longer search pattern ...");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    @Deprecated
    public JSONObject poolSearchLibraryDilution(HttpSession session, JSONObject json) {
        String searchStr = json.getString("str");
        String platformType = json.getString("platform").toUpperCase();
        try {
            if (searchStr.length() > 1) {
                if (LimsUtils.isBase64String(searchStr)) {
                    //Base64-encoded string, most likely a barcode image beeped in. decode and search
                    searchStr = new String(Base64.decodeBase64(searchStr));
                }

                //String str = searchStr.toLowerCase();
                StringBuilder b = new StringBuilder();
                List<LibraryDilution> dilutions = new ArrayList<LibraryDilution>(requestManager
                        .listAllLibraryDilutionsBySearch(searchStr, PlatformType.valueOf(platformType)));
                int numMatches = 0;
                for (LibraryDilution d : dilutions) {
                    /*
                    String dilName = d.getName() == null ? null : d.getName();
                    if (dilName != null &&
                        (dilName.toLowerCase().equals(str) || dilName.toLowerCase().contains(str)) ||
                        (d.getLibrary().getAlias().toLowerCase().contains(str) || d.getLibrary().getName().toLowerCase().contains(str)) ||
                        (d.getLibrary().getSample().getAlias().toLowerCase().contains(str) || d.getLibrary().getSample().getName().toLowerCase().contains(str))) {
                    */
                    b.append(
                            "<div onmouseover=\"this.className='autocompleteboxhighlight'\" onmouseout=\"this.className='autocompletebox'\" class=\"autocompletebox\""
                                    + " onclick=\"Pool.search.poolSearchSelectDilution('" + d.getId() + "', '"
                                    + d.getName() + "')\">" + "<b>Dilution: " + d.getName() + "</b><br/>"
                                    + "<b>Library: " + d.getLibrary().getAlias() + "</b><br/>" + "<b>Sample: "
                                    + d.getLibrary().getSample().getAlias() + "</b><br/>" + "</div>");
                    numMatches++;
                    //}
                }
                if (numMatches == 0) {
                    return JSONUtils.JSONObjectResponse("html", "No matches");
                } else {
                    return JSONUtils.JSONObjectResponse("html",
                            "<div class=\"autocomplete\"><ul>" + b.toString() + "</ul></div>");
                }
            } else {
                return JSONUtils.JSONObjectResponse("html", "Need a longer search pattern ...");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    @Deprecated
    public JSONObject poolSearchEmPcrDilution(HttpSession session, JSONObject json) {
        String searchStr = json.getString("str");
        String platformType = json.getString("platform").toUpperCase();
        try {
            if (searchStr.length() > 1) {
                if (LimsUtils.isBase64String(searchStr)) {
                    //Base64-encoded string, most likely a barcode image beeped in. decode and search
                    searchStr = new String(Base64.decodeBase64(searchStr));
                }
                //String str = searchStr.toLowerCase();
                StringBuilder b = new StringBuilder();
                List<emPCRDilution> dilutions = new ArrayList<emPCRDilution>(requestManager
                        .listAllEmPcrDilutionsBySearch(searchStr, PlatformType.valueOf(platformType)));
                int numMatches = 0;
                for (emPCRDilution d : dilutions) {
                    /*
                    String dilName = d.getName() == null ? null : d.getName();
                    if (dilName != null &&
                        (dilName.toLowerCase().equals(str) || dilName.toLowerCase().contains(str)) ||
                        (d.getLibrary().getAlias().toLowerCase().contains(str) || d.getLibrary().getName().toLowerCase().contains(str)) ||
                        (d.getLibrary().getSample().getAlias().toLowerCase().contains(str) || d.getLibrary().getSample().getName().toLowerCase().contains(str))) {
                    */
                    b.append(
                            "<div onmouseover=\"this.className='autocompleteboxhighlight'\" onmouseout=\"this.className='autocompletebox'\" class=\"autocompletebox\""
                                    + " onclick=\"Pool.search.poolSearchSelectDilution('" + d.getId() + "', '"
                                    + d.getName() + "')\">" + "<b>Dilution: " + d.getName() + "</b><br/>"
                                    + "<b>Library: " + d.getLibrary().getAlias() + "</b><br/>" + "<b>Sample: "
                                    + d.getLibrary().getSample().getAlias() + "</b><br/>" + "</div>");
                    numMatches++;
                    //}
                }
                if (numMatches == 0) {
                    return JSONUtils.JSONObjectResponse("html", "No matches");
                } else {
                    return JSONUtils.JSONObjectResponse("html",
                            "<div class=\"autocomplete\"><ul>" + b.toString() + "</ul></div>");
                }
            } else {
                return JSONUtils.JSONObjectResponse("html", "Need a longer search pattern ...");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject checkPoolExperiment(HttpSession session, JSONObject json) {
        try {
            String partition = json.getString("partition");
            Long poolId = json.getLong("poolId");
            Pool<? extends Poolable> p = requestManager.getPoolById(poolId);
            StringBuilder sb = new StringBuilder();

            if (p.getExperiments().size() == 0) {
                Set<Project> pooledProjects = new HashSet<Project>();
                Collection<? extends Poolable> ds = p.getPoolableElements();
                for (Poolable d : ds) {
                    if (d instanceof Dilution) {
                        pooledProjects.add(((Dilution) d).getLibrary().getSample().getProject());
                    } else if (d instanceof Plate) {
                        Plate plate = (Plate) d;
                        if (!plate.getElements().isEmpty()) {
                            if (plate.getElementType().equals(Library.class)) {
                                Library l = (Library) plate.getElements().get(0);
                                pooledProjects.add(l.getSample().getProject());
                            }
                        }
                    }
                }

                sb.append("<div style='float:left; clear:both'>");
                for (Project project : pooledProjects) {
                    sb.append("<div id='studySelectDiv" + partition + "_" + project.getProjectId() + "'>");
                    sb.append(project.getAlias() + ": <select name='poolStudies" + partition + "_"
                            + project.getProjectId() + "' id='poolStudies" + partition + "_"
                            + project.getProjectId() + "'>");
                    Collection<Study> studies = requestManager.listAllStudiesByProjectId(project.getProjectId());
                    if (studies.isEmpty()) {
                        //throw new Exception("No studies available on project " + project.getName() + ". At least one study must be available for each project associated with this Pool.");
                        return JSONUtils.SimpleJSONError("No studies available on project " + project.getName()
                                + ". At least one study must be available for each project associated with this Pool.");
                    } else {
                        for (Study s : studies) {
                            sb.append("<option value='" + s.getId() + "'>" + s.getAlias() + " (" + s.getName()
                                    + " - " + s.getStudyType() + ")</option>");
                        }
                    }
                    sb.append("</select>");
                    sb.append("<input id='studySelectButton-" + partition + "_" + p.getId()
                            + "' type='button' onclick=\"Run.container.selectStudy('" + partition + "', "
                            + p.getId() + "," + project.getProjectId()
                            + ");\" class=\"ui-state-default ui-corner-all\" value='Select Study'/>");
                    sb.append("</div><br/>");
                }
                sb.append("</div>");
            }

            return JSONUtils.JSONObjectResponse("html", sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject selectStudyForPool(HttpSession session, JSONObject json) {
        try {
            Long poolId = json.getLong("poolId");
            Pool p = requestManager.getPoolById(poolId);

            Long studyId = json.getLong("studyId");
            Study s = requestManager.getStudyById(studyId);

            if (json.has("runId") && json.get("runId") != null) {
                Long runId = json.getLong("runId");
                Run r = requestManager.getRunById(runId);
                if (r != null) {
                    StringBuilder sb = new StringBuilder();

                    Experiment e = dataObjectFactory.getExperiment();
                    e.setAlias("EXP_AUTOGEN_" + s.getName() + "_" + s.getStudyType() + "_"
                            + (s.getExperiments().size() + 1));
                    e.setTitle(s.getProject().getName() + " " + r.getPlatformType().getKey() + " "
                            + s.getStudyType() + " experiment (Auto-gen)");
                    e.setDescription(s.getProject().getAlias());
                    e.setPlatform(r.getSequencerReference().getPlatform());
                    e.setStudy(s);
                    e.setSecurityProfile(s.getSecurityProfile());

                    try {
                        p.addExperiment(e);
                        requestManager.saveExperiment(e);
                    } catch (MalformedExperimentException e1) {
                        e1.printStackTrace();
                    }

                    sb.append("<i>");
                    sb.append("<span>" + s.getProject().getAlias() + " (" + e.getName() + ": "
                            + p.getDilutions().size() + " dilutions)</span><br/>");
                    sb.append("</i>");

                    return JSONUtils.JSONObjectResponse("html", sb.toString());
                } else {
                    return JSONUtils.SimpleJSONError("Could not find run with ID " + runId);
                }
            } else {
                return JSONUtils.SimpleJSONError(
                        "Could not resolve Run ID. Please ensure the run is saved before adding Pools");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject listPoolAverageInsertSizes(HttpSession session, JSONObject json) {
        try {
            JSONObject j = new JSONObject();
            for (Pool<? extends Poolable> pool : requestManager.listAllPools()) {
                StringBuilder b = new StringBuilder();
                Collection<? extends Dilution> dls = pool.getDilutions();
                if (dls.size() > 0) {
                    int sum = 0;
                    int count = 0;
                    for (Dilution ld : dls) {
                        List<LibraryQC> libraryQCs = new ArrayList<LibraryQC>(
                                requestManager.listAllLibraryQCsByLibraryId(ld.getLibrary().getId()));
                        if (libraryQCs.size() > 0) {
                            //List<LibraryQC> libraryQCsList = new ArrayList<LibraryQC>(libraryQCs);
                            //Collections.sort(libraryQCsList);
                            LibraryQC libraryQC = libraryQCs.get(libraryQCs.size() - 1);
                            sum += libraryQC.getInsertSize();
                            count++;
                        }
                    }
                    if (count > 0) {
                        b.append(Math.round(sum / count) + " bp");
                    }
                } else {
                    b.append("No QC");
                }
                j.put(pool.getId(), b.toString());
            }
            return j;
        } catch (IOException e) {
            log.debug("Failed", e);
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject checkAverageInsertSizeByPoolId(HttpSession session, JSONObject json) {
        try {
            JSONObject j = new JSONObject();
            Long poolId = json.getLong("poolId");
            Pool pool = requestManager.getPoolById(poolId);
            StringBuilder b = new StringBuilder();
            Collection<? extends Dilution> dls = pool.getDilutions();
            if (dls.size() > 0) {
                int sum = 0;
                int count = 0;
                for (Dilution ld : dls) {
                    List<LibraryQC> libraryQCs = new ArrayList<LibraryQC>(
                            requestManager.listAllLibraryQCsByLibraryId(ld.getLibrary().getId()));
                    if (libraryQCs.size() > 0) {
                        LibraryQC libraryQC = libraryQCs.get(libraryQCs.size() - 1);
                        sum += libraryQC.getInsertSize();
                        count++;
                    }
                }
                if (count > 0) {
                    b.append(Math.round(sum / count) + " bp");
                }
            } else {
                b.append("No QC");
            }
            j.put("response", b.toString());
            return j;
        } catch (IOException e) {
            log.debug("Failed", e);
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject checkConcentrationByPoolId(HttpSession session, JSONObject json) {
        try {
            JSONObject j = new JSONObject();
            Long poolId = json.getLong("poolId");
            Pool pool = requestManager.getPoolById(poolId);
            double concentration = pool.getConcentration();
            j.put("response", concentration);
            return j;
        } catch (IOException e) {
            log.debug("Failed", e);
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject checkInfoByPoolId(HttpSession session, JSONObject json) {
        try {
            JSONObject j = new JSONObject();
            Long poolId = json.getLong("poolId");
            Pool<? extends Poolable> pool = requestManager.getPoolById(poolId);
            StringBuilder info = new StringBuilder();
            if (pool.getDilutions().size() > 0) {
                info.append("<ul class=\"shorterbullets\">");
                Collection<? extends Dilution> dls = pool.getDilutions();
                for (Dilution dilution : dls) {
                    info.append("<li><b>" + dilution.getName() + "</b>");
                    info.append(
                            "<br/><small><u>" + dilution.getLibrary().getSample().getProject().getAlias() + "</u>");
                    info.append("<br/>" + dilution.getLibrary().getAlias() + " (" + dilution.getLibrary().getName()
                            + ")");
                    info.append("<br/>" + dilution.getLibrary().getDescription() + " ("
                            + dilution.getLibrary().getSample().getName() + ")</small>");
                    info.append("</li>");
                }
                info.append("</ul>");
            } else if (pool.getPoolableElements().size() > 0) {
                info.append("<ul class=\"shorterbullets\">");
                Collection<? extends Poolable> ds = pool.getPoolableElements();
                for (Poolable p : ds) {
                    if (p instanceof Dilution) {
                        Dilution dilution = (Dilution) p;
                        info.append("<li><b>" + dilution.getName() + "</b>");
                        info.append("<br/><small><u>" + dilution.getLibrary().getSample().getProject().getAlias()
                                + "</u>");
                        info.append("<br/>" + dilution.getLibrary().getAlias() + " ("
                                + dilution.getLibrary().getName() + ")");
                        info.append("<br/>" + dilution.getLibrary().getDescription() + " ("
                                + dilution.getLibrary().getSample().getName() + ")</small>");
                        info.append("</li>");
                    } else if (p instanceof Plate) {
                        Plate<LinkedList<Plateable>, Plateable> plate = (Plate<LinkedList<Plateable>, Plateable>) p;
                        info.append("<li><b>" + plate.getName() + "</b> [" + plate.getSize() + "-well]");
                        if (!plate.getElements().isEmpty()) {
                            info.append("<br/><small><u>" + plate.getSize() + "-well "
                                    + plate.getElementType().getSimpleName() + " plate</u>");
                            Plateable element = plate.getElements().getFirst();
                            if (element instanceof Library) {
                                Library l = (Library) element;
                                info.append("<br/><small><u>" + l.getSample().getProject().getAlias() + " ("
                                        + l.getSample().getProject().getName() + ")</u>");
                                info.append("<br/>Platform: " + l.getPlatformName());
                                info.append("<br/>Type: " + l.getLibraryType().getDescription());
                                info.append("<br/>Selection: " + l.getLibrarySelectionType().getName());
                                info.append("<br/>Strategy: " + l.getLibraryStrategyType().getName());
                            } else if (element instanceof Dilution) {
                                Dilution l = (Dilution) element;
                                info.append("<br/><small><u>" + l.getLibrary().getSample().getProject().getAlias()
                                        + " (" + l.getLibrary().getSample().getProject().getName() + ")</u>");
                                info.append("<br/>Platform: " + l.getLibrary().getPlatformName());
                                info.append("<br/>Type: " + l.getLibrary().getLibraryType().getDescription());
                                info.append(
                                        "<br/>Selection: " + l.getLibrary().getLibrarySelectionType().getName());
                                info.append("<br/>Strategy: " + l.getLibrary().getLibraryStrategyType().getName());
                            } else if (element instanceof Sample) {
                                Sample l = (Sample) element;
                                info.append("<br/><small><u>" + l.getProject().getAlias() + " ("
                                        + l.getProject().getName() + ")</u>");
                            }
                        }
                        info.append("</li>");
                    } else {
                        info.append("<li><b>" + p.getName() + "</b>");
                    }
                }
                info.append("</ul>");
            } else {
                info.append("No pooled elements");
            }
            j.put("response", info.toString());
            return j;
        } catch (IOException e) {
            log.debug("Failed", e);
            return JSONUtils.SimpleJSONError(e.getMessage());
        }
    }

    public JSONObject deletePool(HttpSession session, JSONObject json) {
        User user;
        try {
            user = securityManager
                    .getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName());
        } catch (IOException e) {
            e.printStackTrace();
            return JSONUtils.SimpleJSONError("Error getting currently logged in user.");
        }

        if (user != null && user.isAdmin()) {
            if (json.has("poolId")) {
                Long poolId = json.getLong("poolId");
                try {
                    requestManager.deletePool(requestManager.getPoolById(poolId));
                    return JSONUtils.SimpleJSONResponse("Pool deleted");
                } catch (IOException e) {
                    e.printStackTrace();
                    return JSONUtils.SimpleJSONError("Cannot delete pool: " + e.getMessage());
                }
            } else {
                return JSONUtils.SimpleJSONError("No pool specified to delete.");
            }
        } else {
            return JSONUtils.SimpleJSONError("Only logged-in admins can delete objects.");
        }
    }

    public JSONObject listPoolsDataTable(HttpSession session, JSONObject json) {
        if (json.has("platform") && !"".equals(json.getString("platform"))) {
            try {
                String platform = json.getString("platform");
                JSONObject j = new JSONObject();
                JSONArray arr = new JSONArray();
                for (Pool pool : requestManager.listAllPoolsByPlatform(PlatformType.get(platform))) {
                    JSONArray pout = new JSONArray();
                    pout.add(pool.getName());
                    pout.add(pool.getAlias() != null ? pool.getAlias() : "");
                    pout.add(pool.getCreationDate() != null ? pool.getCreationDate().toString() : "");
                    pout.add(pool.getId());
                    pout.add(pool.getId());
                    pout.add(pool.getId());
                    pout.add("<a href=\"/miso/pool/" + pool.getId()
                            + "\"><span class=\"ui-icon ui-icon-pencil\"></span></a>");
                    arr.add(pout);
                }
                j.put("pools", arr);
                return j;
            } catch (IOException e) {
                log.debug("Failed", e);
                return JSONUtils.SimpleJSONError("Failed: " + e.getMessage());
            }
        } else {
            return JSONUtils.SimpleJSONError("No platform specified");
        }
    }

    public JSONObject getPoolableElementInfo(HttpSession session, JSONObject json) {
        if (json.has("poolId") && json.has("elementId")) {
            try {
                Long poolId = json.getLong("poolId");
                Long elementId = json.getLong("elementId");
                Pool<? extends Poolable> pool = requestManager.getPoolById(poolId);
                StringBuilder info = new StringBuilder();
                for (Poolable p : pool.getPoolableElements()) {
                    if (p.getId() == elementId) {
                        if (p instanceof Plate) {
                            Plate<LinkedList<Plateable>, Plateable> plate = (Plate) p;
                            for (Plateable plateable : plate.getElements()) {
                                if (plateable instanceof Plate) {
                                    info.append("<b>Internal Plate:</b> <a href='/miso/plate/" + plate.getId()
                                            + "'>" + plate.getName() + "</a><br/>");
                                } else if (p instanceof Library) {
                                    Library library = (Library) plateable;
                                    info.append("<b>Library:</b> <a href='/miso/library/" + library.getId() + "'>"
                                            + library.getAlias() + "(" + library.getName() + ")</a><br/>");
                                }
                            }
                        } else if (p instanceof Dilution) {
                            Dilution dilution = (Dilution) p;
                            if (dilution instanceof emPCRDilution) {
                                info.append("<b>emPCR:</b> <a href='/miso/empcr/"
                                        + ((emPCRDilution) dilution).getEmPCR().getId() + "'>"
                                        + ((emPCRDilution) dilution).getEmPCR().getName() + "<br/>");
                            }
                            info.append("<b>Library:</b> <a href='/miso/library/" + dilution.getLibrary().getId()
                                    + "'>" + dilution.getLibrary().getAlias() + "("
                                    + dilution.getLibrary().getName() + ")</a><br/>");
                            info.append("<b>Sample:</b> <a href='/miso/sample/"
                                    + dilution.getLibrary().getSample().getId() + "'>"
                                    + dilution.getLibrary().getSample().getAlias() + "("
                                    + dilution.getLibrary().getSample().getName() + ")</a><br/>");
                            if (pool.getPoolableElements().size() > 1) {
                                Map<Integer, TagBarcode> barcodes = dilution.getLibrary().getTagBarcodes();
                                if (!barcodes.isEmpty()) {
                                    info.append("<b>Barcodes:</b></br>");
                                    for (Integer key : dilution.getLibrary().getTagBarcodes().keySet()) {
                                        info.append(key + ":" + barcodes.get(key).getName() + " ("
                                                + barcodes.get(key).getSequence() + ")<br/>");
                                    }
                                    info.append(
                                            "<span class='counter'><img src='/styles/images/status/green.png' border='0'></span>");
                                } else {
                                    info.append("<b>Barcode:</b>");
                                    info.append("<b>Library:</b> <a href='/miso/library/"
                                            + dilution.getLibrary().getId() + "'>Choose tag barcode</a>");
                                    info.append(
                                            "<span class='counter'><img src='/styles/images/status/red.png' border='0'></span>");
                                }
                            }
                        } else {
                            info.append("Unrecognised poolable element: " + p.getClass().getSimpleName());
                        }
                        break;
                    }
                }
                return JSONUtils.JSONObjectResponse("info", info.toString());
            } catch (IOException e) {
                log.debug("Failed", e);
                return JSONUtils.SimpleJSONError("Failed: " + e.getMessage());
            }
        } else {
            return JSONUtils.SimpleJSONError("No pool or element ID specified");
        }
    }

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

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

    public void setDataObjectFactory(DataObjectFactory dataObjectFactory) {
        this.dataObjectFactory = dataObjectFactory;
    }

    public void setBarcodeFactory(BarcodeFactory barcodeFactory) {
        this.barcodeFactory = barcodeFactory;
    }

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

    public void setPrintManager(PrintManager<MisoPrintService, Queue<?>> printManager) {
        this.printManager = printManager;
    }
}