com.act.lcms.db.model.StandardWell.java Source code

Java tutorial

Introduction

Here is the source code for com.act.lcms.db.model.StandardWell.java

Source

/*************************************************************************
*                                                                        *
*  This file is part of the 20n/act project.                             *
*  20n/act enables DNA prediction for synthetic biology/bioengineering.  *
*  Copyright (C) 2017 20n Labs, Inc.                                     *
*                                                                        *
*  Please direct all queries to act@20n.com.                             *
*                                                                        *
*  This program is free software: you can redistribute it and/or modify  *
*  it under the terms of the GNU General Public License as published by  *
*  the Free Software Foundation, either version 3 of the License, or     *
*  (at your option) any later version.                                   *
*                                                                        *
*  This program is distributed in the hope that it will be useful,       *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*  GNU General Public License for more details.                          *
*                                                                        *
*  You should have received a copy of the GNU General Public License     *
*  along with this program.  If not, see <http://www.gnu.org/licenses/>. *
*                                                                        *
*************************************************************************/

package com.act.lcms.db.model;

import com.act.lcms.db.io.DB;
import com.act.lcms.db.io.parser.PlateCompositionParser;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

public class StandardWell extends PlateWell<StandardWell> {
    protected static final StandardWell INSTANCE = new StandardWell();

    public static StandardWell getInstance() {
        return INSTANCE;
    }

    public static final String TABLE_NAME = "wells_standard";

    public enum MEDIA_TYPE {
        WATER, MEOH, YEAST
    };

    private enum DB_FIELD implements DBFieldEnumeration {
        ID(1, -1, "id"), PLATE_ID(2, 1, "plate_id"), PLATE_ROW(3, 2, "plate_row"), PLATE_COLUMN(4, 3,
                "plate_column"), CHEMICAL(5, 4, "chemical"), MEDIA(6, 5,
                        "media"), NOTE(7, 6, "note"), CONCENTRATION(8, 7, "concentration"),;

        private final int offset;
        private final int insertUpdateOffset;
        private final String fieldName;

        DB_FIELD(int offset, int insertUpdateOffset, String fieldName) {
            this.offset = offset;
            this.insertUpdateOffset = insertUpdateOffset;
            this.fieldName = fieldName;
        }

        @Override
        public int getOffset() {
            return offset;
        }

        @Override
        public int getInsertUpdateOffset() {
            return insertUpdateOffset;
        }

        @Override
        public String getFieldName() {
            return fieldName;
        }

        @Override
        public String toString() {
            return this.fieldName;
        }

        public static String[] names() {
            DB_FIELD[] values = DB_FIELD.values();
            String[] names = new String[values.length];
            for (int i = 0; i < values.length; i++) {
                names[i] = values[i].getFieldName();
            }
            return names;
        }
    }

    protected static final List<String> ALL_FIELDS = Collections.unmodifiableList(Arrays.asList(DB_FIELD.names()));

    // id is auto-generated on insertion.
    protected static final List<String> INSERT_UPDATE_FIELDS = INSTANCE.makeInsertUpdateFields();

    @Override
    public String getTableName() {
        return TABLE_NAME;
    }

    @Override
    public List<String> getAllFields() {
        return ALL_FIELDS;
    }

    @Override
    public List<String> getInsertUpdateFields() {
        return INSERT_UPDATE_FIELDS;
    }

    protected static final String GET_BY_ID_QUERY = INSTANCE.makeGetByIDQuery();

    @Override
    protected String getGetByIDQuery() {
        return GET_BY_ID_QUERY;
    }

    protected static final String GET_BY_PLATE_ID_QUERY = INSTANCE.makeGetByPlateIDQuery();

    @Override
    protected String getGetByPlateIDQuery() {
        return GET_BY_PLATE_ID_QUERY;
    }

    protected static final String INSERT_QUERY = INSTANCE.makeInsertQuery();

    @Override
    public String getInsertQuery() {
        return INSERT_QUERY;
    }

    protected static final String UPDATE_QUERY = INSTANCE.makeUpdateQuery();

    @Override
    public String getUpdateQuery() {
        return UPDATE_QUERY;
    }

    @Override
    protected List<StandardWell> fromResultSet(ResultSet resultSet) throws SQLException {
        List<StandardWell> results = new ArrayList<>();
        while (resultSet.next()) {
            Integer id = resultSet.getInt(DB_FIELD.ID.getOffset());
            Integer plateId = resultSet.getInt(DB_FIELD.PLATE_ID.getOffset());
            Integer plateRow = resultSet.getInt(DB_FIELD.PLATE_ROW.getOffset());
            Integer plateColumn = resultSet.getInt(DB_FIELD.PLATE_COLUMN.getOffset());
            String chemical = resultSet.getString(DB_FIELD.CHEMICAL.getOffset());
            String media = resultSet.getString(DB_FIELD.MEDIA.getOffset());
            String note = resultSet.getString(DB_FIELD.NOTE.getOffset());
            Double concentration = resultSet.getDouble(DB_FIELD.CONCENTRATION.getOffset());
            if (resultSet.wasNull()) {
                concentration = null;
            }

            results.add(new StandardWell(id, plateId, plateRow, plateColumn, chemical, media, note, concentration));
        }
        return results;
    }

    public static Boolean isMediaWater(String media) {
        return media.toLowerCase().contains("water") || media.contains("h20");
    }

    public static Boolean doesMediaContainYeastExtract(String media) {
        //TODO: Update this check once we have a new media ID that also corresponds to containing yeast extract.
        return media.toLowerCase().contains("gal");
    }

    public static Boolean isMediaMeOH(String media) {
        return media.toLowerCase().contains("meoh");
    }

    public static final String QUERY_GET_STANDARD_WELL_BY_PLATE_ID_AND_COORDINATES = StringUtils.join(new String[] {
            "SELECT", StringUtils.join(INSTANCE.getAllFields(), ','), "from", INSTANCE.getTableName(),
            "where plate_id = ?", "  and plate_row = ?", "  and plate_column = ?", }, " ");

    public StandardWell getStandardWellsByPlateIdAndCoordinates(DB db, Integer plateId, Integer plateRow,
            Integer plateColumn) throws SQLException, IOException, ClassNotFoundException {
        try (PreparedStatement stmt = db.getConn()
                .prepareStatement(QUERY_GET_STANDARD_WELL_BY_PLATE_ID_AND_COORDINATES)) {
            stmt.setInt(1, plateId);
            stmt.setInt(2, plateRow);
            stmt.setInt(3, plateColumn);
            try (ResultSet resultSet = stmt.executeQuery()) {
                return expectOneResult(resultSet, String.format("plate_id = %d, plate_row = %d, plate_column = %d",
                        plateId, plateRow, plateColumn));
            }
        }
    }

    public static final String QUERY_GET_STANDARD_WELLS_BY_CHEMICAL = StringUtils.join(
            new String[] { "SELECT", StringUtils.join(INSTANCE.getAllFields(), ','), "from",
                    INSTANCE.getTableName(), "where chemical = ?", "order by plate_id, plate_row, plate_column" },
            " ");

    public List<StandardWell> getStandardWellsByChemical(DB db, String chemical) throws SQLException {
        try (PreparedStatement stmt = db.getConn().prepareStatement(QUERY_GET_STANDARD_WELLS_BY_CHEMICAL)) {
            stmt.setString(1, chemical);
            try (ResultSet resultSet = stmt.executeQuery()) {
                return fromResultSet(resultSet);
            }
        }
    }

    public static final String QUERY_GET_STANDARD_WELLS_BY_CHEMICAL_AND_PLATE_ID = StringUtils.join(new String[] {
            "SELECT", StringUtils.join(INSTANCE.getAllFields(), ','), "from", INSTANCE.getTableName(),
            "where chemical = ?", "  and plate_id = ?", "order by plate_id, plate_row, plate_column" }, " ");

    public List<StandardWell> getStandardWellsByChemicalAndPlateId(DB db, String chemical, Integer plateId)
            throws SQLException {
        try (PreparedStatement stmt = db.getConn()
                .prepareStatement(QUERY_GET_STANDARD_WELLS_BY_CHEMICAL_AND_PLATE_ID)) {
            stmt.setString(1, chemical);
            stmt.setInt(2, plateId);
            try (ResultSet resultSet = stmt.executeQuery()) {
                return fromResultSet(resultSet);
            }
        }
    }

    public static final String QUERY_GET_STANDARD_WELLS_BY_CHEMICAL_AND_PLATE_ID_AND_MEDIUM = StringUtils
            .join(new String[] { "SELECT", StringUtils.join(INSTANCE.getAllFields(), ','), "from",
                    INSTANCE.getTableName(), "where chemical = ?", "  and plate_id = ?", "  and media = ?",
                    "order by plate_id, plate_row, plate_column" }, " ");

    public List<StandardWell> getStandardWellsByChemicalAndPlateIdAndMedium(DB db, String chemical, Integer plateId,
            String medium) throws SQLException {
        try (PreparedStatement stmt = db.getConn()
                .prepareStatement(QUERY_GET_STANDARD_WELLS_BY_CHEMICAL_AND_PLATE_ID_AND_MEDIUM)) {
            stmt.setString(1, chemical);
            stmt.setInt(2, plateId);
            stmt.setString(3, medium);
            try (ResultSet resultSet = stmt.executeQuery()) {
                return fromResultSet(resultSet);
            }
        }
    }

    // Insert/update
    protected void bindInsertOrUpdateParameters(PreparedStatement stmt, Integer plateId, Integer plateRow,
            Integer plateColumn, String chemical, String media, String note, Double concentration)
            throws SQLException {
        stmt.setInt(DB_FIELD.PLATE_ID.getInsertUpdateOffset(), plateId);
        stmt.setInt(DB_FIELD.PLATE_ROW.getInsertUpdateOffset(), plateRow);
        stmt.setInt(DB_FIELD.PLATE_COLUMN.getInsertUpdateOffset(), plateColumn);
        stmt.setString(DB_FIELD.CHEMICAL.getInsertUpdateOffset(), chemical);
        stmt.setString(DB_FIELD.MEDIA.getInsertUpdateOffset(), media);
        stmt.setString(DB_FIELD.NOTE.getInsertUpdateOffset(), note);
        if (concentration != null) {
            stmt.setDouble(DB_FIELD.CONCENTRATION.getInsertUpdateOffset(), concentration);
        } else {
            stmt.setNull(DB_FIELD.CONCENTRATION.getInsertUpdateOffset(), Types.DOUBLE);
        }
    }

    @Override
    protected void bindInsertOrUpdateParameters(PreparedStatement stmt, StandardWell sw) throws SQLException {
        bindInsertOrUpdateParameters(stmt, sw.getPlateId(), sw.getPlateRow(), sw.getPlateColumn(), sw.getChemical(),
                sw.getMedia(), sw.getNote(), sw.getConcentration());
    }

    public StandardWell insert(DB db, Integer plateId, Integer plateRow, Integer plateColumn, String chemical,
            String media, String note, Double concentration) throws SQLException, IOException {
        return INSTANCE.insert(db,
                new StandardWell(null, plateId, plateRow, plateColumn, chemical, media, note, concentration));
    }

    // Parsing/loading
    public List<StandardWell> insertFromPlateComposition(DB db, PlateCompositionParser parser, Plate p)
            throws SQLException, IOException {
        Map<Pair<String, String>, String> msids = parser.getCompositionTables().get("chemical");
        List<Pair<String, String>> sortedCoordinates = new ArrayList<>(msids.keySet());
        Collections.sort(sortedCoordinates, new Comparator<Pair<String, String>>() {
            // TODO: parse the values of these pairs as we read them so we don't need this silly comparator.
            @Override
            public int compare(Pair<String, String> o1, Pair<String, String> o2) {
                if (o1.getKey().equals(o2.getKey())) {
                    return Integer.valueOf(Integer.parseInt(o1.getValue()))
                            .compareTo(Integer.parseInt(o2.getValue()));
                }
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        List<StandardWell> results = new ArrayList<>();
        for (Pair<String, String> coords : sortedCoordinates) {
            String chemical = parser.getCompositionTables().get("chemical").get(coords);
            if (chemical == null || chemical.isEmpty()) {
                continue;
            }
            Map<Pair<String, String>, String> mediaMap = parser.getCompositionTables().get("media");
            if (mediaMap == null) {
                mediaMap = parser.getCompositionTables().get("solvent");
            }
            String media = mediaMap != null ? mediaMap.get(coords) : null;
            Map<Pair<String, String>, String> notesMap = parser.getCompositionTables().get("note");
            String note = notesMap != null ? notesMap.get(coords) : null;
            Pair<Integer, Integer> index = parser.getCoordinatesToIndices().get(coords);
            Map<Pair<String, String>, String> concentrationsMap = parser.getCompositionTables()
                    .get("concentration");
            Double concentration = concentrationsMap != null ? Double.parseDouble(concentrationsMap.get(coords))
                    : null;
            StandardWell s = INSTANCE.insert(db, p.getId(), index.getLeft(), index.getRight(), chemical, media,
                    note, concentration);

            results.add(s);
        }

        return results;
    }

    private String chemical;
    private String media;
    private String note;
    private Double concentration;

    private StandardWell() {
    }

    protected StandardWell(Integer id, Integer plateId, Integer plateRow, Integer plateColumn, String chemical,
            String media, String note, Double concentration) {
        this.id = id;
        this.plateId = plateId;
        this.plateRow = plateRow;
        this.plateColumn = plateColumn;
        this.chemical = chemical;
        this.media = media;
        this.note = note;
        this.concentration = concentration;
    }

    public String getChemical() {
        return chemical;
    }

    public void setChemical(String chemical) {
        this.chemical = chemical;
    }

    public String getMedia() {
        return media;
    }

    public void setMedia(String media) {
        this.media = media;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public Double getConcentration() {
        return concentration;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        StandardWell that = (StandardWell) o;

        // TODO: what to do about INSTANCE?

        // TODO: move the BaseDBModel and PlateWell comparisons to the appropriate superclasses.
        // Note that we could probably just restrict this to use plate id, row, and column since those should be unique.
        if (this.id != null && that.id != null && !this.id.equals(that.id))
            return false;
        if (!this.plateId.equals(that.plateId))
            return false;
        if (!this.plateRow.equals(that.plateRow))
            return false;
        if (!this.plateColumn.equals(that.plateColumn))
            return false;

        if (!chemical.equals(that.chemical))
            return false;
        if (media != null ? !media.equals(that.media) : that.media != null)
            return false;
        if (note != null ? !note.equals(that.note) : that.note != null)
            return false;
        return !(concentration != null ? !concentration.equals(that.concentration) : that.concentration != null);

    }

    @Override
    public int hashCode() {
        int result = id == null ? 0 : id.hashCode();
        result = 31 * result + plateId.hashCode();
        result = 31 * result + plateRow.hashCode();
        result = 31 * result + plateColumn.hashCode();
        result = 31 * result + chemical.hashCode();
        result = 31 * result + (media != null ? media.hashCode() : 0);
        result = 31 * result + (note != null ? note.hashCode() : 0);
        result = 31 * result + (concentration != null ? concentration.hashCode() : 0);
        return result;
    }
}