Java tutorial
/* * The Gemma project * * Copyright (c) 2006 University of British Columbia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package ubic.gemma.web.controller.visualization; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; 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 javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.validation.BindException; import org.springframework.validation.ObjectError; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; import ubic.gemma.analysis.preprocess.ExpressionDataMatrixBuilder; import ubic.gemma.analysis.service.CompositeSequenceGeneMapperService; import ubic.gemma.datastructure.matrix.ExpressionDataDoubleMatrix; import ubic.gemma.datastructure.matrix.ExpressionDataMatrixRowElement; import ubic.gemma.expression.experiment.service.ExpressionExperimentService; import ubic.gemma.model.common.measurement.Measurement; import ubic.gemma.model.common.quantitationtype.GeneralType; import ubic.gemma.model.common.quantitationtype.PrimitiveType; import ubic.gemma.model.common.quantitationtype.QuantitationType; import ubic.gemma.model.expression.arrayDesign.ArrayDesign; import ubic.gemma.model.expression.bioAssay.BioAssayService; import ubic.gemma.model.expression.bioAssayData.DesignElementDataVector; import ubic.gemma.model.expression.bioAssayData.DesignElementDataVectorService; import ubic.gemma.model.expression.designElement.CompositeSequence; import ubic.gemma.model.expression.designElement.CompositeSequenceService; import ubic.gemma.model.expression.experiment.ExpressionExperiment; import ubic.gemma.model.expression.experiment.FactorValue; import ubic.gemma.model.genome.Gene; import ubic.gemma.web.controller.BaseFormController; import ubic.gemma.web.propertyeditor.QuantitationTypePropertyEditor; import ubic.gemma.web.util.ConfigurationCookie; /** * A <link>SimpleFormController<link> providing search functionality of genes or design elements (probe sets). The * success view returns either a visual representation of the result set or a downloadable data file. * <p> * {@link viewSampling} sets whether or not just some randomly selected vectors will be shown, and {@link species} sets * the type of species to search. {@link keywords} restrict the search. * <p> * {@link maskMissing} masks the missing values. * * @author keshav * @version $Id: ExpressionExperimentVisualizationFormController.java,v 1.74 2012/06/07 05:17:00 paul Exp $ */ @Deprecated public class ExpressionExperimentVisualizationFormController extends BaseFormController { /** * @author keshav */ static class ExpressionExperimentVisualizationCookie extends ConfigurationCookie { public ExpressionExperimentVisualizationCookie(ExpressionExperimentVisualizationCommand command) { super(COOKIE_NAME); log.debug("creating cookie"); this.setProperty("searchString", command.getSearchString()); this.setProperty("viewSampling", command.isViewSampling()); this.setProperty("maskMissing", command.isMaskMissing()); this.setProperty(SEARCH_CRITERIA, command.getSearchCriteria()); this.setProperty("quantitationTypeName", command.getQuantitationType().getName()); /* set cookie to expire after 2 days. */ this.setMaxAge(172800); this.setComment("User selections for visualization form"); } } private static final String SEARCH_CRITERIA = "searchCriteria"; public static final String SEARCH_BY_PROBE = "probe set id"; public static final String SEARCH_BY_GENE = "gene symbol"; private static final String COOKIE_NAME = "expressionExperimentVisualizationCookie"; private static final int MAX_ELEMENTS_TO_VISUALIZE = 200; protected ExpressionExperimentService expressionExperimentService = null; protected CompositeSequenceService compositeSequenceService = null; protected DesignElementDataVectorService designElementDataVectorService; protected CompositeSequenceGeneMapperService compositeSequenceGeneMapperService = null; protected BioAssayService bioAssayService = null; public ExpressionExperimentVisualizationFormController() { /* * if true, reuses the same command object across the edit-submit-process (get-post-process). */ setSessionForm(true); } /** * @param request * @param response * @param command * @param errors * @return ModelAndView * @throws Exception */ @Override public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { ExpressionExperimentVisualizationCommand eevc = ((ExpressionExperimentVisualizationCommand) command); /* store user choices from command object in a cookie. */ Cookie cookie = new ExpressionExperimentVisualizationCookie(eevc); response.addCookie(cookie); Long id = eevc.getExpressionExperimentId(); ExpressionExperiment expressionExperiment = this.expressionExperimentService.load(id); expressionExperiment = expressionExperimentService.thawLite(expressionExperiment); if (expressionExperiment == null) { return processErrors(request, response, command, errors, "No expression experiment with id " + id + " found"); } // // for ( BioAssay ba : expressionExperiment.getBioAssays() ) { // bioAssayService.thaw( ba ); // } QuantitationType quantitationType = eevc.getQuantitationType(); if (quantitationType == null) { return processErrors(request, response, command, errors, "Quantitation type must be provided"); } Collection<DesignElementDataVector> dataVectors = getVectors(command, errors, eevc, expressionExperiment, quantitationType); if (errors.hasErrors()) { return processErrors(request, response, command, errors, null); } designElementDataVectorService.thaw(dataVectors); ExpressionDataMatrixBuilder matrixBuilder = new ExpressionDataMatrixBuilder(dataVectors); ExpressionDataDoubleMatrix expressionDataMatrix = null; if (eevc.isMaskMissing()) { expressionDataMatrix = matrixBuilder.getProcessedData(); } else { expressionDataMatrix = matrixBuilder.getPreferredData(); } /* * deals with the case where probes don't match for the given quantitation type, or we lack a preferred data * type, or other calamaties. */ if (expressionDataMatrix == null || expressionDataMatrix.rows() == 0) { String message = "None of the probe sets match the given quantitation type " + quantitationType.getType().getValue(); return processErrors(request, response, command, errors, message); } Map<CompositeSequence, Collection<Gene>> genes = getGenes(expressionDataMatrix); // this will slow things // down. /* return the model and view */ ModelAndView mav = new ModelAndView(getSuccessView()); mav.addObject("expressionDataMatrix", expressionDataMatrix); mav.addObject("genes", genes); mav.addObject("expressionExperiment", expressionExperiment); mav.addObject("quantitationType", eevc.getQuantitationType()); mav.addObject(SEARCH_CRITERIA, eevc.getSearchCriteria()); mav.addObject("searchString", eevc.getSearchString()); mav.addObject("viewSampling", new Boolean(eevc.isViewSampling())); mav.addObject("maskMissing", new Boolean(eevc.isMaskMissing())); return mav; } /** * @param request * @param response * @param command * @param errors * @return ModelAndView * @throws Exception */ @Override public ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { ExpressionExperimentVisualizationCommand eevc = ((ExpressionExperimentVisualizationCommand) command); Long id = eevc.getExpressionExperimentId(); if (request.getParameter("cancel") != null) { log.info("Cancelled"); if (id != null) { return new ModelAndView( new RedirectView("/Gemma/expressionExperiment/showExpressionExperiment.html?id=" + id)); } log.warn("Cannot find details view due to null id. Redirecting to overview"); return new ModelAndView( new RedirectView("/Gemma/expressionExperiment/showAllExpressionExperiments.html")); } return super.processFormSubmission(request, response, command, errors); } public void setBioAssayService(BioAssayService bioAssayService) { this.bioAssayService = bioAssayService; } /** * @param compositeSequenceGeneMapperService The compositeSequenceGeneMapperService to set. */ public void setCompositeSequenceGeneMapperService( CompositeSequenceGeneMapperService compositeSequenceGeneMapperService) { this.compositeSequenceGeneMapperService = compositeSequenceGeneMapperService; } /** * @param compositeSequenceService */ public void setCompositeSequenceService(CompositeSequenceService compositeSequenceService) { this.compositeSequenceService = compositeSequenceService; } /** * @param designElementDataVectorService */ public void setDesignElementDataVectorService(DesignElementDataVectorService designElementDataVectorService) { this.designElementDataVectorService = designElementDataVectorService; } /** * @param expressionExperimentService */ public void setExpressionExperimentService(ExpressionExperimentService expressionExperimentService) { this.expressionExperimentService = expressionExperimentService; } /** * @param request * @return Object * @throws ServletException */ @Override protected Object formBackingObject(HttpServletRequest request) { Long id = null; try { id = Long.parseLong(request.getParameter("id")); } catch (NumberFormatException e) { throw new RuntimeException("Id was not valid Long integer", e); } ExpressionExperiment ee = null; ExpressionExperimentVisualizationCommand eevc = new ExpressionExperimentVisualizationCommand(); if (id != null && StringUtils.isNotBlank(id.toString())) { ee = expressionExperimentService.load(id); } else { ee = ExpressionExperiment.Factory.newInstance(); } eevc.setExpressionExperimentId(ee.getId()); eevc.setName(ee.getName()); if (StringUtils.isBlank(request.getParameter(SEARCH_CRITERIA))) { eevc = loadCookie(request, eevc); } return eevc; } /** * @param command * @param errors * @param eevc * @param expressionExperiment * @param quantitationType * @return Collection<DesignElementDataVector> */ protected Collection<DesignElementDataVector> getVectors(Object command, BindException errors, ExpressionExperimentVisualizationCommand eevc, ExpressionExperiment expressionExperiment, QuantitationType quantitationType) { Collection<DesignElementDataVector> vectors = null; Collection<CompositeSequence> compositeSequences = null; boolean viewSampling = ((ExpressionExperimentVisualizationCommand) command).isViewSampling(); Collection<ArrayDesign> arrayDesigns = expressionExperimentService .getArrayDesignsUsed(expressionExperiment); /* check size if 'viewSampling' is set. */ if (viewSampling) { vectors = expressionExperimentService.getSamplingOfVectors(quantitationType, MAX_ELEMENTS_TO_VISUALIZE); } else { String searchString = eevc.getSearchString(); String[] searchIds = StringUtils.split(searchString, ","); if (searchIds.length > MAX_ELEMENTS_TO_VISUALIZE) { String message = "Max elements to search for is " + MAX_ELEMENTS_TO_VISUALIZE; log.error(message); errors.addError(new ObjectError(command.toString(), null, null, message)); return null; } List<String> searchIdsAsList = Arrays.asList(searchIds); /* handle search by design element */ if (eevc.getSearchCriteria().equalsIgnoreCase(SEARCH_BY_PROBE)) { if (arrayDesigns.size() == 0) { String message = "No platforms found for " + expressionExperiment; log.error(message); errors.addError(new ObjectError(command.toString(), null, null, message)); return null; } compositeSequences = compositeSequenceService.findByNamesInArrayDesigns(searchIdsAsList, arrayDesigns); } else if (eevc.getSearchCriteria().equalsIgnoreCase(SEARCH_BY_GENE)) { /* search by gene */ if (arrayDesigns.size() == 0) { String message = "No platforms found for " + expressionExperiment; log.error(message); errors.addError(new ObjectError(command.toString(), null, null, message)); return null; } compositeSequences = getProbesByGeneSymbols(arrayDesigns, searchIdsAsList); } if (compositeSequences == null || compositeSequences.size() == 0) { String message = "Genes/Probes could not be found."; log.error(message); errors.addError(new ObjectError(command.toString(), null, null, message)); return null; } vectors = expressionExperimentService.getDesignElementDataVectors(compositeSequences, quantitationType); } if (vectors == null || vectors.size() == 0) { errors.addError(new ObjectError(command.toString(), null, null, "No data could be found.")); } return vectors; } /** * */ @Override @InitBinder protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) { super.initBinder(binder); binder.registerCustomEditor(QuantitationType.class, new QuantitationTypePropertyEditor(getContinuousQuantitationTypes(request))); } /** * Populates drop downs. * * @param request * @return Map */ @Override protected Map<String, List<? extends Object>> referenceData(HttpServletRequest request) { Map<String, List<? extends Object>> searchByMap = new HashMap<String, List<? extends Object>>(); List<String> searchCategories = new ArrayList<String>(); searchCategories.add(SEARCH_BY_GENE); searchCategories.add(SEARCH_BY_PROBE); searchByMap.put("searchCategories", searchCategories); Collection<QuantitationType> types = getContinuousQuantitationTypes(request); List<QuantitationType> listedTypes = new ArrayList<QuantitationType>(); listedTypes.addAll(types); searchByMap.put("quantitationTypes", listedTypes); return searchByMap; } /** * @param request * @return Collection<QuantitationType> */ private Collection<QuantitationType> getContinuousQuantitationTypes(HttpServletRequest request) { Long id = null; try { id = Long.parseLong(request.getParameter("id")); } catch (NumberFormatException e) { throw new RuntimeException("Id was not valid Long integer", e); } ExpressionExperiment expressionExperiment = this.expressionExperimentService.load(id); Collection<QuantitationType> types = expressionExperimentService.getQuantitationTypes(expressionExperiment); Iterator<QuantitationType> iter = types.iterator(); while (iter.hasNext()) { QuantitationType type = iter.next(); if (!type.getGeneralType().equals(GeneralType.QUANTITATIVE)) { iter.remove(); } } return types; } /** * @param expressionDataMatrix * @return */ private Map<CompositeSequence, Collection<Gene>> getGenes(ExpressionDataDoubleMatrix expressionDataMatrix) { Collection<CompositeSequence> css = new HashSet<CompositeSequence>(); for (ExpressionDataMatrixRowElement el : expressionDataMatrix.getRowElements()) { CompositeSequence cs = el.getDesignElement(); css.add(cs); } return compositeSequenceService.getGenes(css); } /** * @param arrayDesigns * @param searchIdsAsList * @return */ private Collection<CompositeSequence> getProbesByGeneSymbols(Collection<ArrayDesign> arrayDesigns, List<String> searchIdsAsList) { Collection<CompositeSequence> compositeSequences; Map<Gene, Collection<CompositeSequence>> genes2Probes = compositeSequenceGeneMapperService .getGene2ProbeMapByOfficialSymbols(searchIdsAsList, arrayDesigns); compositeSequences = new HashSet<CompositeSequence>(); for (Gene g : genes2Probes.keySet()) { compositeSequences.addAll(genes2Probes.get(g)); log.debug("gene official symbol: " + g.getOfficialSymbol() + " has " + compositeSequences.size() + " composite sequences associated with it."); } return compositeSequences; } /** * A cookie to store the user preferences. * * @param request * @param eevc * @return ExpressionExperimentVisualizationCommand */ private ExpressionExperimentVisualizationCommand loadCookie(HttpServletRequest request, ExpressionExperimentVisualizationCommand eevc) { Collection<QuantitationType> quantitationTypes = getContinuousQuantitationTypes(request); /* * If we don't have any cookies, just return. We probably won't get this situation as we'll always have at least * one cookie (the one with the JSESSION ID). */ if (request == null || request.getCookies() == null) { return null; } for (Cookie cook : request.getCookies()) { if (cook.getName().equals(COOKIE_NAME)) { try { ConfigurationCookie cookie = new ConfigurationCookie(cook); eevc.setSearchString(cookie.getString("searchString")); eevc.setSearchCriteria(cookie.getString(SEARCH_CRITERIA)); eevc.setViewSampling(cookie.getBoolean("viewSampling")); eevc.setMaskMissing(cookie.getBoolean("maskMissing")); /* determine which quantitation type was previously selected */ String qtName = cookie.getString("quantitationTypeName"); for (QuantitationType qt : quantitationTypes) { if (StringUtils.equals(qtName, qt.getName())) { eevc.setQuantitationType(qt); return eevc; } } } catch (Exception e) { log.warn("Cookie could not be loaded: " + e.getMessage()); // that's okay, we just don't get a cookie. } } } /* If we've come this far, we have a cookie but not one that matches COOKIE_NAME. Provide friendly defaults. */ if (quantitationTypes.size() > 0) { QuantitationType qt = quantitationTypes.iterator().next(); eevc.setQuantitationType(qt); } else { throw new RuntimeException("No continuous-valued quantitation types"); } eevc.setSearchString("gene symbol 1, gene symbol 2"); eevc.setViewSampling(true); return eevc; } } class FactorValueComparator implements Comparator<FactorValue> { @Override public int compare(FactorValue arg0, FactorValue arg1) { if (arg0.getMeasurement() != null && arg1.getMeasurement() != null) { return (new MeasurementComparator()).compare(arg0.getMeasurement(), arg1.getMeasurement()); } else if (arg0.getCharacteristics().size() > 0 && arg1.getCharacteristics().size() > 0) { // FIXME implement real comparison. // return CharacteristicUtils.compare( arg0.getCharacteristics().size(), arg1.getCharacteristics().size() ); return -1; } else if (arg0.getValue() != null && arg1.getValue() != null) { return arg0.getValue().compareTo(arg1.getValue()); } else { return arg0.getId().compareTo(arg1.getId()); // fallback. } } } class MeasurementComparator implements Comparator<Measurement> { @Override public int compare(Measurement o1, Measurement o2) { PrimitiveType ptype = o1.getRepresentation(); if (ptype.equals(PrimitiveType.STRING) || ptype.equals(PrimitiveType.BOOLEAN)) { return o1.getValue().compareTo(o2.getValue()); } else if (ptype.equals(PrimitiveType.DOUBLE)) { Double d1 = Double.parseDouble(o1.getValue()); Double d2 = Double.parseDouble(o2.getValue()); return d1.compareTo(d2); } else if (ptype.equals(PrimitiveType.INT)) { Integer d1 = Integer.parseInt(o1.getValue()); Integer d2 = Integer.parseInt(o2.getValue()); return d1.compareTo(d2); } else { throw new UnsupportedOperationException("Don't know how to compare " + ptype + "'s"); } } }