ubic.gemma.analysis.report.ArrayDesignReportServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for ubic.gemma.analysis.report.ArrayDesignReportServiceImpl.java

Source

/*
 * 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.analysis.report;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Component;
import ubic.basecode.util.FileTools;
import ubic.gemma.model.common.Auditable;
import ubic.gemma.model.common.auditAndSecurity.AuditEvent;
import ubic.gemma.model.common.auditAndSecurity.AuditEventService;
import ubic.gemma.model.common.auditAndSecurity.eventType.ArrayDesignGeneMappingEvent;
import ubic.gemma.model.common.auditAndSecurity.eventType.ArrayDesignRepeatAnalysisEvent;
import ubic.gemma.model.common.auditAndSecurity.eventType.ArrayDesignSequenceAnalysisEvent;
import ubic.gemma.model.common.auditAndSecurity.eventType.ArrayDesignSequenceUpdateEvent;
import ubic.gemma.model.common.auditAndSecurity.eventType.AuditEventType;
import ubic.gemma.model.expression.arrayDesign.ArrayDesign;
import ubic.gemma.model.expression.arrayDesign.ArrayDesignService;
import ubic.gemma.model.expression.arrayDesign.ArrayDesignValueObject;
import ubic.gemma.util.ConfigUtils;
import ubic.gemma.util.EntityUtils;

/**
 * @author jsantos
 * @version $Id: ArrayDesignReportServiceImpl.java,v 1.17 2012/11/02 22:34:45 paul Exp $
 */
@Component
public class ArrayDesignReportServiceImpl implements ArrayDesignReportService {
    private String ARRAY_DESIGN_REPORT_DIR = "ArrayDesignReports";

    private String ARRAY_DESIGN_REPORT_FILE_NAME_PREFIX = "ArrayDesignReport";

    // For all array designs
    private String ARRAY_DESIGN_SUMMARY = "AllArrayDesignsSummary";

    @Autowired
    private ArrayDesignService arrayDesignService;

    @Autowired
    private AuditEventService auditEventService;

    /**
     * Batch of classes we can get events for all at once.
     */
    @SuppressWarnings("unchecked")
    private Class<? extends AuditEventType>[] eventTypes = new Class[] { ArrayDesignSequenceUpdateEvent.class,
            ArrayDesignSequenceAnalysisEvent.class, ArrayDesignGeneMappingEvent.class,
            ArrayDesignRepeatAnalysisEvent.class };
    /*
     * ArrayDesignProbeRenamingEvent.class,ArrayDesignMergeEvent.class, ArrayDesignAnnotationFileEvent.class,
     * ArrayDesignSubsumeCheckEvent.class
     */

    private String HOME_DIR = ConfigUtils.getString("gemma.appdata.home");

    private Log log = LogFactory.getLog(this.getClass());

    /**
     * Fill in event information
     * 
     * @param adVos
     */
    @Override
    public void fillEventInformation(Collection<ArrayDesignValueObject> adVos) {

        if (adVos == null || adVos.size() == 0)
            return;

        StopWatch watch = new StopWatch();
        watch.start();

        Collection<Long> ids = new ArrayList<Long>();
        for (Object object : adVos) {
            ArrayDesignValueObject adVo = (ArrayDesignValueObject) object;
            Long id = adVo.getId();
            if (id == null)
                continue;
            ids.add(id);
        }

        if (ids.size() == 0)
            return;

        Collection<Class<? extends AuditEventType>> typesToGet = Arrays.asList(eventTypes);

        Collection<ArrayDesign> arrayDesigns = arrayDesignService.loadMultiple(ids);

        Map<Long, ArrayDesign> idMap = EntityUtils.getIdMap(arrayDesigns);

        Map<Class<? extends AuditEventType>, Map<Auditable, AuditEvent>> events = auditEventService
                .getLastEvents(arrayDesigns, typesToGet);

        Map<Auditable, AuditEvent> geneMappingEvents = events.get(ArrayDesignGeneMappingEvent.class);
        Map<Auditable, AuditEvent> sequenceUpdateEvents = events.get(ArrayDesignSequenceUpdateEvent.class);
        Map<Auditable, AuditEvent> sequenceAnalysisEvents = events.get(ArrayDesignSequenceAnalysisEvent.class);
        Map<Auditable, AuditEvent> repeatAnalysisEvents = events.get(ArrayDesignRepeatAnalysisEvent.class);

        for (ArrayDesignValueObject adVo : adVos) {

            Long id = adVo.getId();
            ArrayDesign ad = idMap.get(id);

            if (geneMappingEvents.containsKey(ad)) {
                AuditEvent event = geneMappingEvents.get(ad);
                if (event != null) {
                    adVo.setLastGeneMapping(event.getDate());
                }
            }

            if (sequenceUpdateEvents.containsKey(ad)) {
                AuditEvent event = sequenceUpdateEvents.get(ad);
                if (event != null) {
                    adVo.setLastSequenceUpdate(event.getDate());
                }
            }

            if (sequenceAnalysisEvents.containsKey(ad)) {
                AuditEvent event = sequenceAnalysisEvents.get(ad);
                if (event != null) {
                    adVo.setLastSequenceAnalysis(event.getDate());
                }
            }
            if (repeatAnalysisEvents.containsKey(ad)) {
                AuditEvent event = repeatAnalysisEvents.get(ad);
                if (event != null) {
                    adVo.setLastRepeatMask(event.getDate());
                }
            }

        }

        watch.stop();
        if (watch.getTime() > 1000)
            log.info("Added event information in " + watch.getTime() + "ms");

    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.analysis.report.ArrayDesignReportService#fillInSubsumptionInfo(java.util.Collection)
     */
    @Override
    public void fillInSubsumptionInfo(Collection<ArrayDesignValueObject> valueObjects) {
        Collection<Long> ids = new ArrayList<Long>();
        for (Object object : valueObjects) {
            ArrayDesignValueObject adVo = (ArrayDesignValueObject) object;
            ids.add(adVo.getId());
        }
        Map<Long, Boolean> isSubsumed = arrayDesignService.isSubsumed(ids);
        Map<Long, Boolean> hasSubsumees = arrayDesignService.isSubsumer(ids);
        Map<Long, Boolean> isMergee = arrayDesignService.isMergee(ids);
        Map<Long, Boolean> isMerged = arrayDesignService.isMerged(ids);

        for (ArrayDesignValueObject adVo : valueObjects) {
            Long id = adVo.getId();
            if (isSubsumed.containsKey(id)) {
                adVo.setIsSubsumed(isSubsumed.get(id));
            }
            if (hasSubsumees.containsKey(id)) {
                adVo.setIsSubsumer(hasSubsumees.get(id));
            }
            if (isMergee.containsKey(id)) {
                adVo.setIsMergee(isMergee.get(id));
            }
            if (isMerged.containsKey(id)) {
                adVo.setIsMerged(isMerged.get(id));
            }
        }

    }

    /**
     * Fill in the probe summary statistics
     * 
     * @param adVos
     */
    @Override
    public void fillInValueObjects(Collection<ArrayDesignValueObject> adVos) {
        for (ArrayDesignValueObject origVo : adVos) {
            ArrayDesignValueObject cachedVo = getSummaryObject(origVo.getId());
            if (cachedVo != null) {
                origVo.setNumProbeSequences(cachedVo.getNumProbeSequences());
                origVo.setNumProbeAlignments(cachedVo.getNumProbeAlignments());
                origVo.setNumProbesToGenes(cachedVo.getNumProbesToGenes());
                origVo.setNumGenes(cachedVo.getNumGenes());
                origVo.setDateCached(cachedVo.getDateCached());
                origVo.setDesignElementCount(cachedVo.getDesignElementCount());
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.analysis.report.ArrayDesignReportService#generateAllArrayDesignReport()
     */
    @Override
    public void generateAllArrayDesignReport() {
        log.info("Generating report summarizing all platforms ... ");

        // obtain time information (for timestamping)
        Date d = new Date(System.currentTimeMillis());
        String timestamp = DateFormatUtils.format(d, "yyyy.MM.dd HH:mm");

        long numCsBioSequences = arrayDesignService.numAllCompositeSequenceWithBioSequences();
        long numCsBlatResults = arrayDesignService.numAllCompositeSequenceWithBlatResults();
        long numCsGenes = arrayDesignService.numAllCompositeSequenceWithGenes();
        long numGenes = arrayDesignService.numAllGenes();

        // create a surrogate ArrayDesignValue object to represent the total of all platforms
        ArrayDesignValueObject adVo = new ArrayDesignValueObject();
        adVo.setNumProbeSequences(Long.toString(numCsBioSequences));
        adVo.setNumProbeAlignments(Long.toString(numCsBlatResults));
        adVo.setNumProbesToGenes(Long.toString(numCsGenes));
        adVo.setNumGenes(Long.toString(numGenes));
        adVo.setDateCached(timestamp);

        try {
            // remove file first
            File f = new File(HOME_DIR + File.separatorChar + ARRAY_DESIGN_REPORT_DIR + File.separatorChar
                    + ARRAY_DESIGN_SUMMARY);
            if (f.exists()) {
                if (!f.canWrite() || !f.delete()) {
                    log.warn("Cannot write to file.");
                    return;
                }
            }
            FileOutputStream fos = new FileOutputStream(HOME_DIR + File.separatorChar + ARRAY_DESIGN_REPORT_DIR
                    + File.separatorChar + ARRAY_DESIGN_SUMMARY);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(adVo);
            oos.flush();
            oos.close();
        } catch (Throwable e) {
            // cannot write to file. Just fail gracefully.
            log.error("Cannot write to file.");
        }
        log.info("Done making reports");
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.analysis.report.ArrayDesignReportService#generateArrayDesignReport()
     */
    @Override
    @Secured({ "GROUP_AGENT" })
    public void generateArrayDesignReport() {
        initDirectories();
        log.info("Generating global report");
        generateAllArrayDesignReport();
        Collection<ArrayDesignValueObject> ads = arrayDesignService.loadAllValueObjects();
        log.info("Creating reports for " + ads.size() + " platforms");
        for (ArrayDesignValueObject ad : ads) {
            generateArrayDesignReport(ad);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * ubic.gemma.analysis.report.ArrayDesignReportService#generateArrayDesignReport(ubic.gemma.model.expression.arrayDesign
     * .ArrayDesignValueObject)
     */
    @Override
    public void generateArrayDesignReport(ArrayDesignValueObject adVo) {

        ArrayDesign ad = arrayDesignService.load(adVo.getId());
        if (ad == null)
            return;

        // obtain time information (for timestamping)
        Date d = new Date(System.currentTimeMillis());
        String timestamp = DateFormatUtils.format(d, "yyyy.MM.dd HH:mm");

        long numProbes = arrayDesignService.getCompositeSequenceCount(ad);
        long numCsBioSequences = arrayDesignService.numCompositeSequenceWithBioSequences(ad);
        long numCsBlatResults = arrayDesignService.numCompositeSequenceWithBlatResults(ad);
        long numCsGenes = arrayDesignService.numCompositeSequenceWithGenes(ad);
        long numGenes = arrayDesignService.numGenes(ad);

        adVo.setDesignElementCount(numProbes);
        adVo.setNumProbeSequences(Long.toString(numCsBioSequences));
        adVo.setNumProbeAlignments(Long.toString(numCsBlatResults));
        adVo.setNumProbesToGenes(Long.toString(numCsGenes));
        adVo.setNumGenes(Long.toString(numGenes));
        adVo.setDateCached(timestamp);

        // check the directory exists.
        String reportDir = HOME_DIR + File.separatorChar + ARRAY_DESIGN_REPORT_DIR;
        File reportDirF = new File(reportDir);
        if (!reportDirF.exists()) {
            reportDirF.mkdirs();
        }

        String reportFileName = reportDir + File.separatorChar + ARRAY_DESIGN_REPORT_FILE_NAME_PREFIX + "."
                + adVo.getId();

        try {
            // remove old file first (possible todo: don't do this until after new file is okayed - maybe this delete
            // isn't needed, just clobber.)

            File f = new File(reportFileName);

            if (f.exists()) {
                if (!f.canWrite() || !f.delete()) {
                    log.error(
                            "Report exists but cannot overwrite, leaving the old one in place: " + reportFileName);
                    return;
                }
            }
            FileOutputStream fos = new FileOutputStream(reportFileName);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(adVo);
            oos.flush();
            oos.close();
        } catch (Throwable e) {
            log.error("Cannot write to file: " + reportFileName);
            return;
        }
        log.info("Generated report for " + ad);
    }

    /*
     * (non-Javadoc)
     * 
     * @see ubic.gemma.analysis.report.ArrayDesignReportService#generateArrayDesignReport(java.lang.Long)
     */
    @Override
    public ArrayDesignValueObject generateArrayDesignReport(Long id) {
        Collection<Long> ids = new ArrayList<Long>();
        ids.add(id);
        Collection<ArrayDesignValueObject> adVo = arrayDesignService.loadValueObjects(ids);
        if (adVo != null && adVo.size() > 0) {
            generateArrayDesignReport(adVo.iterator().next());
            return getSummaryObject(id);
        }
        log.warn("No value objects return for requested platforms");
        return null;

    }

    /**
     * @param id
     * @return
     */
    @Override
    public String getLastGeneMappingEvent(Long id) {
        return getLastEvent(id, ArrayDesignGeneMappingEvent.class);

    }

    /**
     * @param id
     * @return
     */
    @Override
    public String getLastRepeatMaskEvent(Long id) {
        return getLastEvent(id, ArrayDesignRepeatAnalysisEvent.class);
    }

    /**
     * @param id
     * @return
     */
    @Override
    public String getLastSequenceAnalysisEvent(Long id) {
        return getLastEvent(id, ArrayDesignSequenceAnalysisEvent.class);
    }

    /**
     * @param id
     * @return
     */
    @Override
    public String getLastSequenceUpdateEvent(Long id) {
        return getLastEvent(id, ArrayDesignSequenceUpdateEvent.class);
    }

    /**
     * Get the cached summary object that represents all platforms.
     * 
     * @return arrayDesignValueObject the summary object that represents the grand total of all array designs
     */
    @Override
    public ArrayDesignValueObject getSummaryObject() {
        ArrayDesignValueObject adVo = null;
        try {
            File f = new File(HOME_DIR + File.separatorChar + ARRAY_DESIGN_REPORT_DIR + File.separatorChar
                    + ARRAY_DESIGN_SUMMARY);
            if (f.exists()) {
                FileInputStream fis = new FileInputStream(f);
                ObjectInputStream ois = new ObjectInputStream(fis);
                adVo = (ArrayDesignValueObject) ois.readObject();
                ois.close();
                fis.close();
            }
        } catch (Throwable e) {
            return null;
        }
        return adVo;
    }

    /**
     * Get the cached summary objects
     * 
     * @param id
     * @return arrayDesignValueObjects the specified summary object
     */
    public Collection<ArrayDesignValueObject> getSummaryObject(Collection<Long> ids) {
        Collection<ArrayDesignValueObject> adVos = new ArrayList<ArrayDesignValueObject>();
        for (Long id : ids) {
            ArrayDesignValueObject adVo = getSummaryObject(id);
            if (adVo != null) {
                adVos.add(getSummaryObject(id));
            }
        }

        return adVos;
    }

    /**
     * Get a specific cached summary object
     * 
     * @param id
     * @return arrayDesignValueObject the specified summary object
     */
    @Override
    public ArrayDesignValueObject getSummaryObject(Long id) {
        ArrayDesignValueObject adVo = null;
        try {
            File f = new File(HOME_DIR + "/" + ARRAY_DESIGN_REPORT_DIR + File.separatorChar
                    + ARRAY_DESIGN_REPORT_FILE_NAME_PREFIX + "." + id);
            if (f.exists()) {
                FileInputStream fis = new FileInputStream(f);
                ObjectInputStream ois = new ObjectInputStream(fis);
                adVo = (ArrayDesignValueObject) ois.readObject();
                ois.close();
                fis.close();
            }
        } catch (Throwable e) {
            return null;
        }
        return adVo;
    }

    /**
     * @param arrayDesignService the arrayDesignService to set
     */
    public void setArrayDesignService(ArrayDesignService arrayDesignService) {
        this.arrayDesignService = arrayDesignService;
    }

    /**
     * FIXME this could be refactored and used elsewhere. This is similar to code in the AuditableService/Dao.
     * 
     * @param id
     * @param eventType
     * @return
     */
    private String getLastEvent(Long id, Class<? extends AuditEventType> eventType) {
        ArrayDesign ad = arrayDesignService.load(id);

        if (ad == null)
            return "";

        List<AuditEvent> events2 = auditEventService.getEvents(ad);

        String analysisEventString = "";
        List<AuditEvent> events = new ArrayList<AuditEvent>();

        for (AuditEvent event : events2) {
            if (event == null)
                continue; // legacy of ordered-list which could end up with gaps; should not be needed
                          // any more
            if (event.getEventType() != null && eventType.isAssignableFrom(event.getEventType().getClass())) {
                events.add(event);
            }
        }

        if (events.size() == 0) {
            return "[None]";
        }

        // add the most recent events to the report. fixme check there are events.
        AuditEvent lastEvent = events.get(events.size() - 1);
        analysisEventString = DateFormatUtils.format(lastEvent.getDate(), "yyyy.MMM.dd hh:mm aa");

        return analysisEventString;
    }

    private void initDirectories() {
        FileTools.createDir(HOME_DIR);
        FileTools.createDir(HOME_DIR + File.separator + ARRAY_DESIGN_REPORT_DIR);
    }

}