es.uvigo.ei.sing.adops.datatypes.BatchProjectOutput.java Source code

Java tutorial

Introduction

Here is the source code for es.uvigo.ei.sing.adops.datatypes.BatchProjectOutput.java

Source

/*-
 * #%L
 * ADOPS
 * %%
 * Copyright (C) 2012 - 2017 David Reboiro-Jato, Miguel Reboiro-Jato, Jorge Vieira, Florentino Fdez-Riverola, Cristina P. Vieira, Nuno A. Fonseca
 * %%
 * 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/gpl-3.0.html>.
 * #L%
 */
package es.uvigo.ei.sing.adops.datatypes;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

public class BatchProjectOutput extends Observable implements Observer {
    private final static Logger LOG = Logger.getLogger(BatchProjectOutput.class);

    private static final String STATUS_FILE = "status.txt";

    private final BatchProject project;

    private final Map<File, Project> projects;
    private final Map<Project, ExperimentOutput> projectOutputs;
    private final Map<Project, Throwable> projectErrors;

    public BatchProjectOutput(BatchProject project) {
        super();
        this.project = project;

        this.projects = new LinkedHashMap<>();
        this.projectOutputs = new HashMap<>();
        this.projectErrors = new HashMap<>();

        try {
            this.load();
        } catch (IOException e) {
            LOG.error("Error loading batch project output", e);

            throw new RuntimeException("Error loading batch project output", e);
        }
    }

    private int getProjectIndex(Project project) {
        final File[] projectDirectories = this.project.getProjectDirectories();

        for (int i = 0; i < projectDirectories.length; i++) {
            if (projectDirectories[i].equals(project.getFolder()))
                return i;
        }

        return -1;
    }

    private void load() throws IOException {
        final File statusFile = new File(this.project.getFolder(), BatchProjectOutput.STATUS_FILE);
        if (!statusFile.exists())
            return;

        synchronized (this.projects) {
            for (String line : FileUtils.readLines(statusFile)) {
                final String projectName = line.substring(0, line.indexOf('='));
                final File projectDir = new File(this.project.getFolder(), projectName);
                final String status = line.substring(line.indexOf('=') + 1);

                if (projectDir.exists()) {
                    final Project project = new Project(projectDir);

                    this.projects.put(this.project.getFastaFiles()[this.getProjectIndex(project)], project);

                    if (status.startsWith("Executed")) {
                        this.projectOutputs.put(project, project.getExperiments().get(0).getResult());
                    } else if (status.startsWith("Error")) {
                        this.projectErrors.put(project, new Exception(status.substring(6, status.length() - 1)));
                    }
                }
            }
        }
    }

    private void store() throws IOException {
        synchronized (this.projects) {
            final File summary = new File(this.project.getFolder(), BatchProjectOutput.STATUS_FILE);
            final List<String> lines = new LinkedList<>();

            final File[] fastaFiles = this.project.getFastaFiles();
            for (int i = 0; i < fastaFiles.length; i++) {
                final File projectDir = this.project.getProjectDirectories()[i];
                final Project project = this.projects.get(fastaFiles[i]);

                if (project == null) {
                    lines.add(projectDir.getName() + "=Unexecuted");
                } else if (this.projectOutputs.containsKey(project)) {
                    lines.add(projectDir.getName() + "=Executed");
                } else if (this.projectErrors.containsKey(project)) {
                    lines.add(
                            projectDir.getName() + "=Error[" + this.projectErrors.get(project).getMessage() + "]");
                } else {
                    lines.add(projectDir.getName() + "=Unexecuted");
                }
            }

            FileUtils.writeLines(summary, lines);
        }
    }

    public int numProjects() {
        return this.project.getFastaFiles().length;
    }

    public Project getProject(int projectIndex) throws IllegalArgumentException, IOException {
        if (projectIndex < 0 || projectIndex > this.numProjects())
            throw new IndexOutOfBoundsException("Illegal project index: " + projectIndex);

        synchronized (this.projects) {
            final File fastaFile = this.project.getFastaFiles()[projectIndex];

            if (!this.projects.containsKey(fastaFile)) {
                final File projectDir = this.project.getProjectDirectories()[projectIndex];

                try {
                    final Project project = new Project(this.project.getConfiguration(), projectDir, fastaFile,
                            true);
                    this.projects.put(fastaFile, project);
                    project.addObserver(this);
                } catch (Exception e) {
                    final Project project = new Project(this.project.getConfiguration(), projectDir, fastaFile,
                            true, false);
                    this.projects.put(fastaFile, project);
                    this.projectErrors.put(project, e);
                }

                this.store();
            }

            return this.projects.get(fastaFile);
        }
    }

    public boolean isFinished() {
        synchronized (this.projects) {
            final Set<Project> projects = new HashSet<>(this.projects.values());

            projects.removeAll(this.projectErrors.keySet());
            projects.removeAll(this.projectOutputs.keySet());

            return projects.isEmpty();
        }
    }

    public boolean hasResults() {
        return !(this.projectOutputs.isEmpty() && this.projectErrors.isEmpty());
    }

    public boolean hasResult(Project project) {
        return this.projectOutputs.containsKey(project) || this.projectErrors.containsKey(project);
    }

    public boolean isReady(Project project) {
        return !this.hasResult(project);
    }

    public boolean isRunning(Project project) {
        return !project.getExperiments().isEmpty() && project.getExperiments().get(0).isRunning();
    }

    public boolean isFinished(Project project) {
        return this.projectOutputs.containsKey(project);
    }

    public boolean isError(Project project) {
        return this.projectErrors.containsKey(project);
    }

    public void addResult(Project project, ExperimentOutput result) {
        this.projectOutputs.put(project, result);

        try {
            this.store();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.setChanged();
        this.notifyObservers(project);

    }

    public void addResult(Project project, Throwable exception) {
        this.projectErrors.put(project, exception);

        try {
            this.store();
        } catch (IOException e) {
            LOG.error("Error storing result in batch project", e);

            throw new RuntimeException("Error storing result in batch project", e);
        }

        this.setChanged();
        this.notifyObservers(project);
    }

    public ExperimentOutput getProjectOutput(Project project) {
        return this.projectOutputs.get(project);
    }

    public Throwable getProjectError(Project project) {
        return this.projectErrors.get(project);
    }

    public void clear() {
        synchronized (this.projects) {
            for (File file : this.projects.keySet()) {
                final Project project = this.projects.remove(file);
                try {
                    project.delete();
                    project.deleteObserver(this);
                } catch (IOException e) {
                    LOG.error("Error deleting project in batch project", e);
                }
            }

            this.projects.clear();
            this.projectOutputs.clear();
            this.projectErrors.clear();

            try {
                this.store();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        this.setChanged();
        this.notifyObservers(arg);
    }

    public Collection<Project> getCreatedProjects() {
        return this.projects.values();
    }
}