org.openmicroscopy.shoola.agents.dataBrowser.view.WellsModel.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.agents.dataBrowser.view.WellsModel.java

Source

/*
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2015 University of Dundee. All rights reserved.
 *
 *
 *  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 2 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, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */
package org.openmicroscopy.shoola.agents.dataBrowser.view;

import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;

import org.openmicroscopy.shoola.agents.dataBrowser.DataBrowserAgent;
import org.openmicroscopy.shoola.agents.dataBrowser.DataBrowserLoader;
import org.openmicroscopy.shoola.agents.dataBrowser.DataBrowserTranslator;
import org.openmicroscopy.shoola.agents.dataBrowser.PlateSaver;
import org.openmicroscopy.shoola.agents.dataBrowser.ThumbnailFieldsLoader;
import org.openmicroscopy.shoola.agents.dataBrowser.ThumbnailProvider;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.BrowserFactory;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.CellDisplay;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageDisplay;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageNode;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.ImageSet;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.Thumbnail;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.WellImageSet;
import org.openmicroscopy.shoola.agents.dataBrowser.browser.WellSampleNode;
import org.openmicroscopy.shoola.agents.dataBrowser.layout.LayoutFactory;
import org.openmicroscopy.shoola.agents.dataBrowser.visitor.DecoratorVisitor;
import omero.gateway.model.TableResult;
import omero.gateway.SecurityContext;
import org.openmicroscopy.shoola.util.image.geom.Factory;
import org.openmicroscopy.shoola.util.ui.PlateGrid;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import org.openmicroscopy.shoola.util.ui.WellGridElement;
import org.openmicroscopy.shoola.util.ui.colourpicker.ColourObject;
import omero.gateway.model.DataObject;
import omero.gateway.model.ImageData;
import omero.gateway.model.PlateData;
import omero.gateway.model.WellData;
import omero.gateway.model.WellSampleData;

/** 
 * A concrete model for a plate.
 *
 * @author  Jean-Marie Burel     
 * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @author Donald MacDonald &nbsp;&nbsp;&nbsp;&nbsp;
 * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
 * @version 3.0
 * <small>
 * (<b>Internal version:</b> $Revision: $Date: $)
 * </small>
 * @since 3.0-Beta3
 */
class WellsModel extends DataBrowserModel {

    /** The number of rows. */
    private int rows;

    /** The number of columns. */
    private int columns;

    /** The dimension of a well. */
    private Dimension wellDimension;

    /** The collection of nodes hosting the wells. */
    private List<ImageDisplay> wellNodes;

    /** The collection of nodes used to display cells e.g. A-1. */
    private Set<CellDisplay> cells;

    /** The number of fields per well. */
    private int fieldsNumber;

    /** The selected field. */
    private int selectedField;

    /** Indicates how to display a row. */
    private int rowSequenceIndex;

    /** Indicates how to display a column. */
    private int columnSequenceIndex;

    /** Value indicating if the wells are valid or not. */
    private List<WellGridElement> validWells;

    /** Flag indicating to load or not the thumbnails. */
    private boolean withThumbnails;

    /** The selected nodes. */
    private List<WellImageSet> selectedNodes;

    /** 
     * Sorts the passed nodes by row.
     * 
     * @param nodes The nodes to sort.
     * @return See above.
     */
    private List<ImageDisplay> sortByRow(Set nodes) {
        List<ImageDisplay> l = new ArrayList<ImageDisplay>();
        if (nodes == null)
            return l;
        Iterator i = nodes.iterator();
        while (i.hasNext()) {
            l.add((ImageDisplay) i.next());
        }
        Comparator c = new Comparator() {
            public int compare(Object o1, Object o2) {
                WellData w1 = (WellData) ((WellImageSet) o1).getHierarchyObject(),
                        w2 = (WellData) ((WellImageSet) o2).getHierarchyObject();
                int n1 = w1.getRow();
                int n2 = w2.getRow();
                int v = 0;
                if (n1 < n2)
                    v = -1;
                else if (n1 > n2)
                    v = 1;
                else if (n1 == n2) {
                    int c1 = w1.getColumn();
                    int c2 = w2.getColumn();
                    if (c1 < c2)
                        v = -1;
                    else if (c1 > c2)
                        v = 1;
                }
                return v;
            }
        };
        Collections.sort(l, c);
        return l;
    }

    /**
     * Creates the color related to the passed Well.
     * 
     * @param data The well to handle.
     * @return See above.
     */
    private Color createColor(WellData data) {
        int red = data.getRed();
        int green = data.getGreen();
        int blue = data.getBlue();
        int alpha = data.getAlpha();
        if (red < 0 || green < 0 || blue < 0 || alpha < 0)
            return null;
        if (red > 255 || green > 255 || blue > 255 || alpha > 255)
            return null;
        return new Color(red, green, blue, alpha);
    }

    /**
     * Returns <code>true</code> if the passed description are the same, 
     * <code>false</code> otherwise.
     * 
     * @param d1 The color to handle.
     * @param d2 The color to handle.
     * @return See above.
     */
    private boolean isSameDescription(String d1, String d2) {
        if (d1 == null && d2 == null)
            return true;
        if (d1 == null && d2 != null)
            return false;
        if (d1 != null && d2 == null)
            return false;
        if (d1 != null && d2 != null) {
            String t1 = d1.trim();
            String t2 = d2.trim();
            if (t1 != null && t2 != null)
                return t1.equals(t2);
            return false;
        }
        return false;
    }

    /**
     * Handles the selection of a cell
     * 
     * @param cell The selected cell.
     * @param well The well to handle.
     * @param results The collection of objects to update.
     */
    private void handleCellSelection(CellDisplay cell, WellImageSet well, List<DataObject> results) {
        String description = cell.getDescription();
        Color c = cell.getHighlight();
        WellData data = (WellData) well.getHierarchyObject();
        data.setWellType(description);
        well.setDescription(description);
        results.add(data);
        if (c == null || !cell.isSpecified()) {
            data.setRed(null);
        } else {
            data.setRed(c.getRed());
            data.setGreen(c.getGreen());
            data.setBlue(c.getBlue());
            data.setAlpha(c.getAlpha());
        }
        well.setHighlight(c);
    }

    /**
     * Creates a new instance.
     * 
     * @param ctx The security context.
     * @param parent   The parent of the wells.
     * @param wells    The collection to wells the model is for.
     * @param withThumbnails Pass <code>true</code> to load the thumbnails,
      *                    <code>false</code> otherwise.
     */
    WellsModel(SecurityContext ctx, Object parent, Set<WellData> wells, boolean withThumbnails) {
        super(ctx);
        if (wells == null)
            throw new IllegalArgumentException("No wells.");
        this.withThumbnails = withThumbnails;
        selectedNodes = new ArrayList<WellImageSet>();
        wellDimension = null;
        this.parent = parent;
        wellNodes = sortByRow(DataBrowserTranslator.transformHierarchy(wells));

        PlateData plate = (PlateData) parent;
        columnSequenceIndex = plate.getColumnSequenceIndex();
        rowSequenceIndex = plate.getRowSequenceIndex();
        selectedField = plate.getDefaultSample();
        if (selectedField < 0)
            selectedField = 0;
        Set<ImageDisplay> samples = new HashSet<ImageDisplay>();
        cells = new HashSet<CellDisplay>();
        rows = -1;
        columns = -1;
        int row, column;
        Iterator<ImageDisplay> j = wellNodes.iterator();
        WellImageSet node;
        ImageNode selected;
        int f;
        String columnSequence;
        String rowSequence;
        Map<Integer, ColourObject> cMap = new HashMap<Integer, ColourObject>();
        Map<Integer, ColourObject> rMap = new HashMap<Integer, ColourObject>();
        WellData data;
        String type;
        ColourObject co;
        Color color;
        boolean b;
        validWells = new ArrayList<WellGridElement>();
        int minRow = -1;
        int minColumn = -1;
        while (j.hasNext()) {
            node = (WellImageSet) j.next();
            row = node.getRow();
            column = node.getColumn();
            data = (WellData) node.getHierarchyObject();
            type = data.getWellType();
            if (cMap.containsKey(column)) {
                co = cMap.get(column);
                color = createColor(data);
                if (!UIUtilities.isSameColors(co.getColor(), color, true)
                        || !isSameDescription(co.getDescription(), type)) {
                    co.setColor(null);
                    co.setDescription(null);
                    cMap.put(column, co);
                }
            } else {
                cMap.put(column, new ColourObject(createColor(data), type));
            }

            if (rMap.containsKey(row)) {
                co = rMap.get(row);
                color = createColor(data);
                if (!UIUtilities.isSameColors(co.getColor(), color, true)
                        || !isSameDescription(co.getDescription(), type)) {
                    co.setColor(null);
                    co.setDescription(null);
                    rMap.put(row, co);
                }
            } else {
                rMap.put(row, new ColourObject(createColor(data), type));
            }
            if (row > rows)
                rows = row;
            if (column > columns)
                columns = column;

            if (minRow < 0 || minRow > row) {
                minRow = row;
            }

            if (minColumn < 0 || minColumn > column) {
                minColumn = column;
            }
            columnSequence = "";
            if (columnSequenceIndex == PlateData.ASCENDING_LETTER)
                columnSequence = UIUtilities.LETTERS.get(column + 1);
            else if (columnSequenceIndex == PlateData.ASCENDING_NUMBER)
                columnSequence = "" + (column + 1);
            rowSequence = "";
            if (rowSequenceIndex == PlateData.ASCENDING_LETTER)
                rowSequence = UIUtilities.LETTERS.get(row + 1);
            else if (rowSequenceIndex == PlateData.ASCENDING_NUMBER)
                rowSequence = "" + (row + 1);
            node.setCellDisplay(columnSequence, rowSequence);
            f = node.getNumberOfSamples();
            if (fieldsNumber < f)
                fieldsNumber = f;
            node.setSelectedWellSample(selectedField);
            selected = node.getSelectedWellSample();
            //set the title to Row/Column
            node.formatWellSampleTitle();
            samples.add(selected);
            b = false;
            if (node.isSampleValid()) {
                wellDimension = selected.getThumbnail().getOriginalSize();
                b = true;
            }
            validWells.add(new WellGridElement(row, column, b));
        }
        //
        if (minRow >= 0 || minColumn >= 0) {
            j = wellNodes.iterator();
            while (j.hasNext()) {
                node = (WellImageSet) j.next();
                if (minRow > 0)
                    node.setIndentRow(minRow);
                if (minColumn > 0)
                    node.setIndentColumn(minColumn);
                if (node.getRow() == minRow || node.getColumn() == minColumn)
                    node.formatWellSampleTitle();
            }
        }

        columns++;
        rows++;
        CellDisplay cell;
        for (int k = 1; k <= columns; k++) {
            columnSequence = "";
            if (columnSequenceIndex == PlateData.ASCENDING_LETTER)
                columnSequence = UIUtilities.LETTERS.get(k + 1);
            else if (columnSequenceIndex == PlateData.ASCENDING_NUMBER)
                columnSequence = "" + k;
            cell = new CellDisplay(k - 1, columnSequence);
            co = cMap.get(k - 1);
            if (co != null) {
                cell.setHighlight(co.getColor());
                cell.setDescription(co.getDescription());
            }
            //if (!isMac)
            //samples.add(cell);
            //cells.add(cell);
        }
        for (int k = 1; k <= rows; k++) {
            rowSequence = "";
            if (rowSequenceIndex == PlateData.ASCENDING_LETTER)
                rowSequence = UIUtilities.LETTERS.get(k);
            else if (rowSequenceIndex == PlateData.ASCENDING_NUMBER)
                rowSequence = "" + k;

            cell = new CellDisplay(k - 1, rowSequence, CellDisplay.TYPE_VERTICAL);
            co = rMap.get(k - 1);
            if (co != null) {
                cell.setHighlight(co.getColor());
                cell.setDescription(co.getDescription());
            }
            //if (!isMac)
            //samples.add(cell);
            //cells.add(cell);
        }
        browser = BrowserFactory.createBrowser(samples);
        browser.accept(new DecoratorVisitor(getCurrentUser().getId()));

        layoutBrowser(LayoutFactory.PLATE_LAYOUT);
        if (wellDimension == null)
            wellDimension = new Dimension(ThumbnailProvider.THUMB_MAX_WIDTH, ThumbnailProvider.THUMB_MAX_HEIGHT);
    }

    /**
     * Indicates how to display a column. 
     * 
     * @return See above.
     */
    int getColumnSequenceIndex() {
        if (columnSequenceIndex == PlateData.ASCENDING_LETTER)
            return PlateGrid.ASCENDING_LETTER;
        return PlateGrid.ASCENDING_NUMBER;
    }

    /**
     * Indicates how to display a row. 
     * 
     * @return See above.
     */
    int getRowSequenceIndex() {
        if (rowSequenceIndex == PlateData.ASCENDING_LETTER)
            return PlateGrid.ASCENDING_LETTER;
        return PlateGrid.ASCENDING_NUMBER;
    }

    /** 
     * Returns an array indicating the valid wells.
     * 
     * @return See above.
     */
    List<WellGridElement> getValidWells() {
        return validWells;
    }

    /**
     * Returns the number of fields per well.
     * 
     * @return See above.
     */
    int getFieldsNumber() {
        return fieldsNumber;
    }

    /**
     * Returns the selected field, the default value is <code>0</code>.
     * 
     * @return See above.
     */
    int getSelectedField() {
        return selectedField;
    }

    /**
     * Sets the selected well. This should only be needed for the fields
     * view.
     * 
     * @param node The selected node.
     */
    void setSelectedWell(WellImageSet node) {
        if (selectedNodes != null)
            selectedNodes.clear();
        List<WellImageSet> l = new ArrayList<WellImageSet>(1);
        l.add(node);
        setSelectedWells(l);
    }

    /**
     * Sets the selected wells. This should only be needed for the fields
     * view.
     * 
     * @param node The selected node.
     */
    void setSelectedWells(List<WellImageSet> nodes) {
        if (nodes == null)
            selectedNodes.clear();
        else
            selectedNodes = nodes;
    }

    /**
     * Returns the selected well.
     * 
     * @return See above.
     */
    WellImageSet getSelectedWell() {
        if (selectedNodes == null || selectedNodes.size() == 0)
            return null;
        return selectedNodes.get(0);
    }

    /**
     * Returns the collection of selected wells.
     * 
     * @return See above.
     */
    List<WellImageSet> getSelectedWells() {
        return selectedNodes;
    }

    /**
     * Views the selected field.
     * 
     * @param index The index of the field to view.
     */
    void viewField(int index) {
        if (index < 0 || index >= fieldsNumber)
            return;
        selectedField = index;
        Set<ImageDisplay> samples = new HashSet<ImageDisplay>();
        List<ImageDisplay> l = getNodes();
        Iterator<ImageDisplay> i = l.iterator();
        WellImageSet well;
        int row = -1;
        int col = -1;
        Collection<ImageDisplay> c = browser.getSelectedDisplays();
        Map<Integer, Integer> location = new HashMap<Integer, Integer>();
        WellSampleNode selected;
        if (c != null && c.size() > 0) {
            Iterator<ImageDisplay> j = c.iterator();
            Object object;
            while (j.hasNext()) {
                object = j.next();
                if (object instanceof WellSampleNode) {
                    selected = (WellSampleNode) object;
                    location.put(selected.getRow(), selected.getColumn());
                }
            }
        }
        List<ImageDisplay> nodes = new ArrayList<ImageDisplay>();
        while (i.hasNext()) {
            well = (WellImageSet) i.next();
            well.setSelectedWellSample(index);
            selected = (WellSampleNode) well.getSelectedWellSample();
            row = selected.getRow();
            if (location.containsKey(row)) {
                col = location.get(row);
                if (selected.getColumn() == col)
                    nodes.add(selected);
            }
            samples.add(selected);
        }
        samples.addAll(cells);
        browser.refresh(samples, nodes);
        layoutBrowser(LayoutFactory.PLATE_LAYOUT);
        //quietly save the field.

        PlateData plate = (PlateData) parent;
        long userID = DataBrowserAgent.getUserDetails().getId();
        if (plate.getOwner().getId() == userID) {
            plate.setDefaultSample(selectedField);
            List<DataObject> list = new ArrayList<DataObject>();
            list.add(plate);
            DataBrowserLoader loader = new PlateSaver(component, ctx, list);
            loader.load();
        }
    }

    /**
     * Sets the tabular data.
     * 
     * @param data The value to set.
     */
    void setTabularData(List<TableResult> data) {
        List<ImageDisplay> nodes = getNodes();
        if (nodes == null || nodes.size() == 0)
            return;
        Iterator<ImageDisplay> i = nodes.iterator();
        WellImageSet well;
        while (i.hasNext()) {
            well = (WellImageSet) i.next();
            well.setTabularData(data);
        }
    }

    /**
     * Sets the values for the row or the column.
     * Returns the collection of wells to update.
     * 
     * @param cell The selected cell.
     */
    void setSelectedCell(CellDisplay cell) {
        if (cell == null)
            return;
        List<DataObject> results = new ArrayList<DataObject>();
        List<ImageDisplay> l = getNodes();
        Iterator<ImageDisplay> i = l.iterator();
        WellImageSet well;
        int index = cell.getIndex();
        if (cell.getType() == CellDisplay.TYPE_HORIZONTAL) {
            while (i.hasNext()) {
                well = (WellImageSet) i.next();
                if (well.getColumn() == index) {
                    handleCellSelection(cell, well, results);
                }
            }
        } else {
            while (i.hasNext()) {
                well = (WellImageSet) i.next();
                if (well.getRow() == index) {
                    handleCellSelection(cell, well, results);
                }
            }
        }
        if (results.size() > 0) {
            DataBrowserLoader loader = new PlateSaver(component, ctx, results);
            loader.load();
        }
    }

    /**
     * Sets the passed node as the current node.
     * 
     * @param node See above.
     */
    void setSelectedField(WellSampleNode node) {
        browser.setSelectedDisplay(node, false, true);
    }

    /**
     * Returns the number of rows.
     * 
     * @return See above.
     */
    int getRows() {
        return rows;
    }

    /**
     * Returns the number of columns.
     * 
     * @return See above.
     */
    int getColumns() {
        return columns;
    }

    /**
     * Returns <code>true</code> is the selected well corresponds to the passed
     * one, <code>false</code> otherwise.
     * 
     * @param row     The row identifying the well.
     * @param column The column identifying the well.
     * @return See above.
     */
    boolean isSameWell(int row, int column) {
        WellImageSet selectedNode = getSelectedWell();
        if (selectedNode == null)
            return false;
        return (selectedNode.getRow() == row && selectedNode.getColumn() == column);
    }

    /**
     * Returns the well corresponding to the passed location.
     * 
     * @param row     The row identifying the well.
     * @param column The column identifying the well.
     * @return See above.
     */
    WellImageSet getWell(int row, int column) {
        List<ImageDisplay> l = getNodes();
        Iterator<ImageDisplay> i = l.iterator();
        WellImageSet well;
        while (i.hasNext()) {
            well = (WellImageSet) i.next();
            if (well.getColumn() == column && well.getRow() == row)
                return well;
        }
        return null;
    }

    /**
     * Creates a concrete loader.
     * 
     * @param row The row identifying the well.
     * @param column The column identifying the well.
     * @return See above.
     */
    DataBrowserLoader createFieldsLoader(int row, int column) {
        List<ImageDisplay> l = getNodes();
        Iterator<ImageDisplay> i = l.iterator();
        ImageSet node;
        List<DataObject> images = new ArrayList<DataObject>();
        WellSampleData data;
        Thumbnail thumb;
        WellImageSet wis;
        List<WellSampleNode> nodes;
        Iterator<WellSampleNode> j;
        WellSampleNode n;
        if (selectedNodes != null)
            selectedNodes.clear();
        while (i.hasNext()) {
            node = (ImageSet) i.next();
            if (node instanceof WellImageSet) {
                wis = (WellImageSet) node;
                if (wis.getRow() == row && wis.getColumn() == column) {
                    setSelectedWell(wis);
                    nodes = wis.getWellSamples();
                    j = nodes.iterator();
                    while (j.hasNext()) {
                        n = j.next();
                        data = (WellSampleData) n.getHierarchyObject();

                        if (data.getId() < 0) {
                            thumb = n.getThumbnail();
                            thumb.setValid(false);
                            thumb.setFullScaleThumb(
                                    Factory.createDefaultImageThumbnail(wellDimension.width, wellDimension.height));
                        } else
                            images.add(data.getImage());
                    }
                }
            }
        }

        if (images.size() == 0)
            return null;
        return new ThumbnailFieldsLoader(component, ctx, images, row, column);
    }

    /**
     * Creates a concrete loader.
     * @see DataBrowserModel#createDataLoader(boolean, Collection)
     */
    protected List<DataBrowserLoader> createDataLoader(boolean refresh, Collection ids) {
        if (!withThumbnails)
            return null;

        List<ImageDisplay> l = getNodes();
        Iterator<ImageDisplay> i = l.iterator();
        ImageSet node;
        List<DataObject> images = new ArrayList<DataObject>();
        ImageNode selected;
        WellSampleData data;
        Thumbnail thumb;
        while (i.hasNext()) {
            node = (ImageSet) i.next();
            if (node instanceof WellImageSet) {
                selected = ((WellImageSet) node).getSelectedWellSample();
                data = (WellSampleData) selected.getHierarchyObject();
                if (data.getId() < 0) {
                    thumb = selected.getThumbnail();
                    thumb.setValid(false);
                    thumb.setFullScaleThumb(
                            Factory.createDefaultImageThumbnail(wellDimension.width, wellDimension.height));
                } else {
                    ImageData img = data.getImage();
                    if (CollectionUtils.isEmpty(ids) || ids.contains(img.getId()))
                        images.add(data.getImage());
                }
            }
        }

        if (images.size() == 0)
            return null;
        return createThumbnailsLoader(sorter.sort(images));
    }

    /**
     * Returns the type of this model.
     * @see DataBrowserModel#getType()
     */
    protected int getType() {
        return DataBrowserModel.WELLS;
    }

    /**
     * No-operation implementation in our case.
     * @see DataBrowserModel#getNodes()
     */
    protected List<ImageDisplay> getNodes() {
        return wellNodes;
    }

}