package plugins.matrix.manager; import java.util.ArrayList; import java.util.List; import matrix.DataMatrixInstance; import org.molgenis.data.Data; import org.molgenis.framework.db.Database; import org.molgenis.framework.db.DatabaseException; import org.molgenis.framework.db.QueryRule; import org.molgenis.framework.db.QueryRule.Operator; import org.molgenis.framework.ui.ApplicationController; import org.molgenis.util.Tuple; public class Browser { /** * Supposed to contain ONLY navigational logic to move around in the matrix * viewer. */ private BrowserModel model = new BrowserModel(); private ApplicationController ac; public BrowserModel getModel() { return model; } public Browser(Data selectedData, DataMatrixInstance instance, ApplicationController ac) throws Exception { this.ac = ac; // create instance of complete matrix and run checks model.setInstance(instance); model.setColMax(instance.getNumberOfCols()); model.setRowMax(instance.getNumberOfRows()); runChecks(selectedData); // set defaults for first view model.setStepSize(5); model.setHeight(10); model.setWidth(5); model.setColStart(0); model.setRowStart(0); model.setColStop(model.getColMax() < model.getWidth() ? model.getColMax() : model.getWidth()); model.setRowStop(model.getRowMax() < model.getHeight() ? model.getRowMax() : model.getHeight()); // set first submatrix using the defaults updateSubmatrix(); } private void runChecks(Data selectedData) throws DatabaseException { if (model.getColMax() < 1) { throw new DatabaseException("Datamatrix '" + selectedData.getName() + "' has no columns."); } if (model.getRowMax() < 1) { throw new DatabaseException("Datamatrix '" + selectedData.getName() + "' has no rows."); } } public void updateSubmatrixKeepRows() throws Exception { setStartAndStops(); List<String> rowNames = this.getModel().getSubMatrix().getRowNames(); List<String> colNames = this.getModel().getInstance().getColNames() .subList(model.getColStart(), model.getColStop()); // create and set submatrix DataMatrixInstance subMatrix = model.getInstance().getSubMatrix(rowNames, colNames); model.setSubMatrix(subMatrix); // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, subMatrix); } public void updateSubmatrixKeepCols() throws Exception { setStartAndStops(); List<String> rowNames = this.getModel().getInstance().getRowNames() .subList(model.getRowStart(), model.getRowStop()); List<String> colNames = this.getModel().getSubMatrix().getColNames(); // create and set submatrix DataMatrixInstance subMatrix = model.getInstance().getSubMatrix(rowNames, colNames); model.setSubMatrix(subMatrix); // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, subMatrix); } private void updateSubmatrix() throws Exception { // helper vars int nRows = model.getRowStop() - model.getRowStart(); int nCols = model.getColStop() - model.getColStart(); // create and set submatrix DataMatrixInstance subMatrix = model.getInstance().getSubMatrixByOffset(model.getRowStart(), nRows, model.getColStart(), nCols); model.setSubMatrix(subMatrix); // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, subMatrix); } private void setStartAndStops() { verifyColStart(); verifyRowStart(); determineColStop(); determineRowStop(); } private void moveActionFollowup() throws Exception { setStartAndStops(); updateSubmatrix(); } /** * On vertical move actions at the right edge of the matrix combined with a * width setting increase past the edge, the horizontal window would move * out of range. The colStop is verified, but this is based on colStart * which can be wrong at that point. Same goes for horizontal move actions * under inverse conditions. This function compensates. */ private void verifyColStart() { if (model.getColStart() + model.getWidth() > model.getColMax()) { if (model.getWidth() > model.getColMax()) { model.setColStart(0); } else { model.setColStart(model.getColMax() - model.getWidth()); } } } /** * On horizontal move actions at the bottom edge of the matrix combined with * a height setting increase past the edge, the vertical window would move * out of range. The rowStop is verified, but this is based on rowStart * which can be wrong at that point. Same goes for vertical move actions * under inverse conditions. This function compensates. */ private void verifyRowStart() { if (model.getRowStart() + model.getHeight() > model.getRowMax()) { if (model.getHeight() > model.getRowMax()) { model.setRowStart(0); } else { model.setRowStart(model.getRowMax() - model.getHeight()); } } } /** * Determine value for column stop. If width is smaller than maximum column * value, the stop position is the current column position plus the width. * If the maximum column value is equal ('perfect fit') or smaller ('window * cut-off') than the width, the stop position is the maximum possible value * for column instead. */ private void determineColStop() { if (model.getWidth() < model.getColMax()) { model.setColStop(model.getColStart() + model.getWidth()); } else { model.setColStop(model.getColMax()); } } /** * Determine value for row stop. If height is smaller than maximum row * value, the stop position is the current row position plus the height. If * the maximum row value is equal ('perfect fit') or smaller ('window * cut-off') than the height, the stop position is the maximum possible * value for row instead. */ private void determineRowStop() { if (model.getHeight() < model.getRowMax()) { model.setRowStop(model.getRowStart() + model.getHeight()); } else { model.setRowStop(model.getRowMax()); } } /** * Moves viewed sub matrix to the right. The step size is added to the * current column position. If this new column position exceeds the maximum * column value minus the width ('window size'), it is set to this maximum * 'window size' value instead. If the width is greater than the maximum * possible column value, the matrix fits inside the 'viewing window' and * the column position is set to zero. */ public void moveRight() throws Exception { if (model.getWidth() < model.getColMax()) { model.setColStart(model.getColStart() + model.getStepSize() > model.getColMax() - model.getWidth() ? model .getColMax() - model.getWidth() : model.getColStart() + model.getStepSize()); } else { model.setColStart(0); } moveActionFollowup(); } /** * Moves viewed sub matrix to the left. The step size is subtracted from the * current column position. If this new column position is less than 0, it * is set to 0 instead. */ public void moveLeft() throws Exception { model.setColStart(model.getColStart() - model.getStepSize() < 0 ? 0 : model.getColStart() - model.getStepSize()); moveActionFollowup(); } public void moveDown() throws Exception { if (model.getHeight() < model.getRowMax()) { model.setRowStart(model.getRowStart() + model.getStepSize() > model.getRowMax() - model.getHeight() ? model .getRowMax() - model.getHeight() : model.getRowStart() + model.getStepSize()); } else { model.setRowStart(0); } moveActionFollowup(); } /** * Moves viewed sub matrix upwards. The step size is subtracted from the * current row position. If this new row position is less than 0, it is set * to 0 instead. */ public void moveUp() throws Exception { model.setRowStart(model.getRowStart() - model.getStepSize() < 0 ? 0 : model.getRowStart() - model.getStepSize()); moveActionFollowup(); } public void moveFarRight() throws Exception { int colStart = model.getColMax() - model.getWidth(); model.setColStart(colStart < 0 ? 0 : colStart); moveActionFollowup(); } public void moveFarLeft() throws Exception { model.setColStart(0); moveActionFollowup(); } public void moveFarDown() throws Exception { int rowStart = model.getRowMax() - model.getHeight(); model.setRowStart(rowStart < 0 ? 0 : rowStart); moveActionFollowup(); } public void moveFarUp() throws Exception { model.setRowStart(0); moveActionFollowup(); } /** * Update can be used after setting new width, height or stepsize. It * behaves like a move action, except there is no movement. This will update * the submatrix to the new dimensions. * * @throws Exception */ public void update() throws Exception { moveActionFollowup(); } /** * Apply filters to values in the matrix to either the whole matrix or * current visible matrix. * * @param request * @throws Exception */ public String applyFilters(Tuple request, Database db, MatrixManagerModel screenModel) throws Exception { String filter = null; DataMatrixInstance filterMatrix = null; String action = request.getString("__action"); if (action.startsWith("filter_visible_")) { // get the current submatrix (view) filterMatrix = this.getModel().getSubMatrix(); } else if (action.startsWith("filter_all_")) { // get the original complete matrix filterMatrix = this.getModel().getInstance(); } else { throw new Exception("filter not prepended with filter_all_ or filter_visible_"); } String field = null; String operator = null; Object value = null; if (action.endsWith("by_index")) { screenModel.setSelectedFilterDiv("filter1"); field = request.getString("add_filter_by_indexFILTER_FIELD"); operator = request.getString("add_filter_by_indexFILTER_OPERATOR"); value = request.getObject("add_filter_by_indexFILTER_VALUE"); QueryRule q = new QueryRule(field, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrixFilterByIndex(q); } else if (action.endsWith("by_col_value")) { screenModel.setSelectedFilterDiv("filter2"); field = request.getString("add_filter_by_col_valueFILTER_FIELD"); operator = request.getString("add_filter_by_col_valueFILTER_OPERATOR"); value = request.getObject("add_filter_by_col_valueFILTER_VALUE"); QueryRule q = new QueryRule(field, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrixFilterByColMatrixValues(q); } else if (action.endsWith("by_row_value")) { screenModel.setSelectedFilterDiv("filter3"); field = request.getString("add_filter_by_row_valueFILTER_FIELD"); operator = request.getString("add_filter_by_row_valueFILTER_OPERATOR"); value = request.getObject("add_filter_by_row_valueFILTER_VALUE"); QueryRule q = new QueryRule(field, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrixFilterByRowMatrixValues(q); } else if (action.endsWith("by_col_attrb")) { screenModel.setSelectedFilterDiv("filter4"); field = request.getString("add_filter_by_col_attrbFILTER_FIELD"); operator = request.getString("add_filter_by_col_attrbFILTER_OPERATOR"); value = request.getObject("add_filter_by_col_attrbFILTER_VALUE"); QueryRule q = new QueryRule(field, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrixFilterByColEntityValues(db, q); } else if (action.endsWith("by_row_attrb")) { screenModel.setSelectedFilterDiv("filter5"); field = request.getString("add_filter_by_row_attrbFILTER_FIELD"); operator = request.getString("add_filter_by_row_attrbFILTER_OPERATOR"); value = request.getObject("add_filter_by_row_attrbFILTER_VALUE"); QueryRule q = new QueryRule(field, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrixFilterByRowEntityValues(db, q); } this.model.setSubMatrix(filterMatrix); filter = action.replace("_", " ") + ", " + field + " " + operator.toLowerCase() + " " + value; // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, this.model.getSubMatrix()); model.setWidth(this.model.getSubMatrix().getNumberOfCols()); model.setHeight(this.model.getSubMatrix().getNumberOfRows()); setStartAndStops(); return filter; } // kept seperate from regular filters for now - highly experimental stuff :) public String apply2DFilter(Tuple request, Database db) throws Exception { String filter = null; DataMatrixInstance filterMatrix = null; String action = request.getString("__action"); if (action.startsWith("2d_filter_visible_")) { // get the current submatrix (view) filterMatrix = this.getModel().getSubMatrix(); } else if (action.startsWith("2d_filter_all_")) { // get the original complete matrix filterMatrix = this.getModel().getInstance(); } else { throw new Exception("filter not prepended with 2d_filter_all_ or 2d_filter_visible_"); } String amount = null; String operator = null; Object value = null; if (action.endsWith("row")) { amount = request.getString("2d_filter_by_row_AMOUNT"); operator = request.getString("2d_filter_by_row_FILTER_OPERATOR"); value = request.getObject("2d_filter_by_row_FILTER_VALUE"); QueryRule q = new QueryRule(amount, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrix2DFilterByRow(q); } else if (action.endsWith("col")) { amount = request.getString("2d_filter_by_col_AMOUNT"); operator = request.getString("2d_filter_by_col_FILTER_OPERATOR"); value = request.getObject("2d_filter_by_col_FILTER_VALUE"); QueryRule q = new QueryRule(amount, Operator.valueOf(operator), value); filterMatrix = filterMatrix.getSubMatrix2DFilterByCol(q); } this.model.setSubMatrix(filterMatrix); filter = action.replace("_", " ") + ", " + amount + " " + operator.toLowerCase() + " " + value; // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, this.model.getSubMatrix()); model.setWidth(this.model.getSubMatrix().getNumberOfCols()); model.setHeight(this.model.getSubMatrix().getNumberOfRows()); setStartAndStops(); return filter; } public String applySelect(Tuple request, Database db, MatrixManagerModel screenModel) throws Exception { String action = request.getString("__action"); if (action.endsWith("cols")) { screenModel.setSelectedFilterDiv("filter8"); List<String> colNames = new ArrayList<String>(); for (String colName : this.getModel().getInstance().getColNames()) { if (request.getString("colselect_" + colName) != null) { colNames.add(colName); } } if (colNames.size() == 0) { throw new Exception("No column names were selected!"); } List<String> rowNames = null; if (action.contains("preserverows")) { rowNames = this.getModel().getSubMatrix().getRowNames(); } else { rowNames = this.getModel().getInstance().getRowNames(); } this.model.setSubMatrix(this.model.getInstance().getSubMatrix(rowNames, colNames)); // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, this.model.getSubMatrix()); model.setWidth(this.model.getSubMatrix().getNumberOfCols()); model.setHeight(this.model.getSubMatrix().getNumberOfRows()); setStartAndStops(); return "custom column selection"; } else if (action.endsWith("rows")) { screenModel.setSelectedFilterDiv("filter9"); List<String> rowNames = new ArrayList<String>(); for (String rowName : this.getModel().getInstance().getRowNames()) { if (request.getString("rowselect_" + rowName) != null) { rowNames.add(rowName); } } if (rowNames.size() == 0) { throw new Exception("No row names were selected!"); } List<String> colNames = null; if (action.contains("preservecols")) { colNames = this.getModel().getSubMatrix().getColNames(); } else { colNames = this.getModel().getInstance().getColNames(); } this.model.setSubMatrix(this.model.getInstance().getSubMatrix(rowNames, colNames)); // store pointer for csv download 'visible' ac.sessionVariables.put(MatrixManager.SESSION_MATRIX_DATA, this.model.getSubMatrix()); model.setWidth(this.model.getSubMatrix().getNumberOfCols()); model.setHeight(this.model.getSubMatrix().getNumberOfRows()); setStartAndStops(); return "custom row selection"; } return null; } }