Skip to content

Commit

Permalink
parameter rework, logging and exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Schmoho committed Jul 26, 2024
1 parent f782543 commit 83610f1
Show file tree
Hide file tree
Showing 65 changed files with 789 additions and 598 deletions.
59 changes: 29 additions & 30 deletions src/main/java/edu/ucsd/sbrg/ModelPolisherCLILauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,21 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import javax.xml.stream.XMLStreamException;

import edu.ucsd.sbrg.annotation.AnnotationException;
import edu.ucsd.sbrg.annotation.adb.ADBSBMLAnnotator;
import edu.ucsd.sbrg.annotation.bigg.BiGGSBMLAnnotator;
import edu.ucsd.sbrg.io.*;
import edu.ucsd.sbrg.parameters.CommandLineParameters;
import edu.ucsd.sbrg.db.adb.AnnotateDB;
import edu.ucsd.sbrg.db.bigg.BiGGDB;
import edu.ucsd.sbrg.io.IOOptions;
import edu.ucsd.sbrg.io.ModelReader;
import edu.ucsd.sbrg.io.ModelWriter;
import edu.ucsd.sbrg.io.SBMLFileUtils;
import edu.ucsd.sbrg.parameters.OutputParameters;
import edu.ucsd.sbrg.polishing.SBMLPolisher;
import edu.ucsd.sbrg.reporting.PolisherProgressBar;
import edu.ucsd.sbrg.reporting.ProgressInitialization;
Expand Down Expand Up @@ -62,7 +58,7 @@
* - HTML tag correction in SBML files.
* - SBML document validation and conversion.
* - Annotation of models using external databases.
* - Output management including file writing, COMBINE archive creation, and compression.
* - Output management including file writing, COMBINE archive creation, and outputType.
* <p>
* This class also handles error logging and provides detailed logging of the processing steps.
*
Expand Down Expand Up @@ -118,12 +114,7 @@ public ModelPolisherCLILauncher(String... args) {
public void commandLineMode(AppConf appConf) {
SBProperties args = appConf.getCmdArgs();

try {
parameters = new CommandLineParameters(args);
} catch (IllegalArgumentException exc1) {
throw new IllegalArgumentException(exc1.getLocalizedMessage());
}

parameters = new CommandLineParameters(args);
registry = new IdentifiersOrg();

if (parameters.annotationParameters().biggAnnotationParameters().annotateWithBiGG()) {
Expand All @@ -136,7 +127,7 @@ public void commandLineMode(AppConf appConf) {

try {
var input = parameters.input();
var output = parameters.outputParameters().outputFile();
var output = parameters.output();

// Check if the input exists, throw an exception if it does not
if (!input.exists()) {
Expand All @@ -154,10 +145,18 @@ public void commandLineMode(AppConf appConf) {
// Ensure the output directory or file's parent directory exists
SBMLFileUtils.checkCreateOutDir(output);

batchProcess(input, parameters.outputParameters().outputFile());
batchProcess(input, parameters.output());

} catch (XMLStreamException | IOException exc) {
exc.printStackTrace();
} catch (ModelReaderException | ModelValidatorException | ModelWriterException | IOException |
AnnotationException e) {
// TODO: produce some user-friendly output and log to a file that can be provided for trouble-shooting
throw new RuntimeException(e);
} catch (IllegalArgumentException exc1) {
// TODO: produce some user-friendly output and log to a file that can be provided for trouble-shooting
throw new IllegalArgumentException(exc1.getLocalizedMessage());
} catch (SQLException e) {
// TODO: produce some user-friendly output and log to a file that can be provided for trouble-shooting
throw new RuntimeException(e);
}
}

Expand All @@ -166,12 +165,9 @@ public void commandLineMode(AppConf appConf) {
* Processes the specified input and output paths. If the input is a directory, it recursively processes each file within.
*
* @param input Path to the input file or directory to be processed. This should correspond to {@link CommandLineParameters#input()}.
* @param output Path to the output file or directory where processed files should be saved.
* This should correspond to {@link OutputParameters#outputFile()}.
* @throws IOException if the input file or directory does not exist, or if no files are found within the directory.
* @throws XMLStreamException if an error occurs during file processing, propagated from {@link ModelPolisherCLILauncher#processFile(File, File)}.
* @param output Path to the output file or directory where processed files should be saved. This should correspond to {@link CommandLineParameters#output()}.
*/
private void batchProcess(File input, File output) throws IOException, XMLStreamException {
private void batchProcess(File input, File output) throws ModelReaderException, ModelWriterException, ModelValidatorException, AnnotationException, SQLException {
// If the input is a directory, process each file within it
if (input.isDirectory()) {
File[] files = input.listFiles();
Expand All @@ -195,7 +191,7 @@ private void batchProcess(File input, File output) throws IOException, XMLStream
}


private void processFile(File input, File output) throws XMLStreamException, IOException {
private void processFile(File input, File output) throws ModelReaderException, ModelWriterException, ModelValidatorException, AnnotationException, SQLException {
long startTime = System.currentTimeMillis();

SBMLDocument doc = new ModelReader(parameters.sboParameters(), registry).read(input);
Expand All @@ -214,7 +210,10 @@ private void processFile(File input, File output) throws XMLStreamException, IOE
o.initialize(new ProgressInitialization(count));
}

new SBMLPolisher(parameters.polishingParameters(), parameters.sboParameters(), registry, polishingObservers).polish(doc);
new SBMLPolisher(
parameters.polishingParameters(),
parameters.sboParameters(),
registry, polishingObservers).polish(doc);

for (var o : polishingObservers) {
o.finish(null);
Expand All @@ -227,8 +226,8 @@ private void processFile(File input, File output) throws XMLStreamException, IOE
}

if (parameters.annotationParameters().biggAnnotationParameters().annotateWithBiGG()) {
new BiGGSBMLAnnotator(bigg, parameters.annotationParameters().biggAnnotationParameters(), parameters.sboParameters(),
registry, annotationObservers).annotate(doc);
new BiGGSBMLAnnotator(bigg, parameters.annotationParameters().biggAnnotationParameters(), parameters.sboParameters(),
registry, annotationObservers).annotate(doc);
}

if (parameters.annotationParameters().adbAnnotationParameters().addADBAnnotations()) {
Expand All @@ -239,12 +238,12 @@ private void processFile(File input, File output) throws XMLStreamException, IOE
o.finish(null);
}

new ModelWriter(parameters.outputParameters()).write(doc, output, getVersionNumber());
output = new ModelWriter(parameters.outputType()).write(doc, output);

if (parameters.SBMLValidation()) {
var mv = new ModelValidator(parameters.outputParameters());
var mv = new ModelValidator();
// use offline validation
mv.validate(output, false);
mv.validate(output);
}

// Log the time taken to process the file
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/edu/ucsd/sbrg/ModelPolisherOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ public interface ModelPolisherOptions extends KeyProvider {
/**
* @author Andreas Dr&auml;ger
*/
enum Compression {
enum OutputType {

GZIP("gz"),
NONE("none"),
ZIP("zip");
SBML("xml"),
JSON("json"),
COMBINE("combine");

@JsonValue
private final String extension;

Compression() {
this(null);
OutputType() {
this(null);
}

Compression(String extension) {
OutputType(String extension) {
this.extension = extension;
}

Expand Down Expand Up @@ -74,8 +74,8 @@ public String getFileExtension() {
* so, which archive type should be used.
*/
@SuppressWarnings("unchecked")
Option<Compression> COMPRESSION_TYPE =
new Option<>("COMPRESSION_TYPE", Compression.class, MESSAGES.getString("COMPR_DESC"), Compression.NONE);
Option<OutputType> OUTPUT_TYPE =
new Option<>("OUTPUT_TYPE", OutputType.class, MESSAGES.getString("COMPR_DESC"), OutputType.SBML);
/**
* This XHTML file defines alternative document notes and makes them
* exchangeable.
Expand Down
67 changes: 14 additions & 53 deletions src/main/java/edu/ucsd/sbrg/ModelValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,39 @@

import de.zbit.io.ZIPUtils;
import de.zbit.util.ResourceManager;
import edu.ucsd.sbrg.parameters.OutputParameters;
import org.sbml.jsbml.SBMLDocument;
import org.sbml.jsbml.SBMLError;
import org.sbml.jsbml.SBMLErrorLog;
import org.sbml.jsbml.SBMLReader;
import org.sbml.jsbml.validator.SBMLValidator;
import org.sbml.jsbml.validator.offline.LoggingValidationContext;

import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import static java.text.MessageFormat.format;

public class ModelValidator {
/**
* Bundle for ModelPolisher logger messages
*/
private static final ResourceBundle MESSAGES = ResourceManager.getBundle("edu.ucsd.sbrg.polisher.Messages");
/**
* A {@link Logger} for this class.
*/
private static final Logger logger = Logger.getLogger(ModelValidator.class.getName());
private final OutputParameters parameters;

public ModelValidator(OutputParameters parameters) {
this.parameters = parameters;
}

/**
* Validates an SBML file either online or offline based on the provided parameters.
* Online validation refers to checking the file against a remote service or database, using specific parameters for the validation process.
* Offline validation involves reading the file locally, handling different compression formats if necessary, and validating the SBML document against local constraints.
* Errors encountered during the validation process are logged for further analysis.
*
* @param outputFile The file object of the SBML file to be validated.
* @param online A boolean flag indicating whether to perform online (true) or offline (false) validation.
*/
public void validate(File outputFile, boolean online) {
String fileExtension = parameters.compression().getFileExtension();
String filename = outputFile.getAbsolutePath() + "." + fileExtension;
public void validate(File outputFile) throws ModelValidatorException {
try {
String filename = outputFile.getAbsolutePath();

if (online) {
logger.info(format(MESSAGES.getString("VAL_ONLINE"), filename));
String output = "xml";
String offcheck = "p,u";
Map<String, String> parameters = new HashMap<>();
parameters.put("output", output);
parameters.put("offcheck", offcheck);
logger.info("Validating " + filename + "\n");
SBMLErrorLog sbmlErrorLog = SBMLValidator.checkConsistency(filename, parameters);
handleErrorLog(sbmlErrorLog, filename);
} else {
logger.info(format(MESSAGES.getString("VAL_OFFLINE"), filename));
SBMLDocument doc = null;
try {
InputStream istream;
if (filename.endsWith(".gz")) {
istream = ZIPUtils.GUnzipStream(filename);
} else if (filename.endsWith(".zip")) {
istream = ZIPUtils.ZIPunCompressStream(filename);
} else {
istream = new FileInputStream(filename);
}
doc = SBMLReader.read(istream);
} catch (XMLStreamException | IOException e) {
e.printStackTrace();
InputStream istream;
if (filename.endsWith(".gz")) {
istream = ZIPUtils.GUnzipStream(filename);
} else if (filename.endsWith(".zip")) {
istream = ZIPUtils.ZIPunCompressStream(filename);
} else {
istream = new FileInputStream(filename);
}
doc = SBMLReader.read(istream);
if (doc != null) {
LoggingValidationContext context = new LoggingValidationContext(doc.getLevel(), doc.getVersion());
context.loadConstraints(SBMLDocument.class);
Expand All @@ -85,6 +44,8 @@ public void validate(File outputFile, boolean online) {
} else {
logger.severe(format(MESSAGES.getString("VAL_OFFLINE_FAIL"), filename));
}
} catch (XMLStreamException | IOException e) {
throw new ModelValidatorException(e, outputFile);
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/edu/ucsd/sbrg/ModelValidatorException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package edu.ucsd.sbrg;

import java.io.File;

public class ModelValidatorException extends Exception {

private final File outputFile;

public ModelValidatorException(Exception e, File outputFile) {
super(e);
this.outputFile = outputFile;
}

public File outputFile() {
return outputFile;
}
}
10 changes: 8 additions & 2 deletions src/main/java/edu/ucsd/sbrg/annotation/AbstractAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import edu.ucsd.sbrg.reporting.ProgressUpdate;
import edu.ucsd.sbrg.reporting.ReportType;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -19,18 +20,23 @@ public AbstractAnnotator(List<ProgressObserver> observers) {
this.observers = observers;
}

public void annotate(List<SBMLElement> elementsToAnnotate) {
public void annotate(List<SBMLElement> elementsToAnnotate) throws SQLException {
throw new UnsupportedOperationException();
}

abstract public void annotate(SBMLElement elementToAnnotate);
abstract public void annotate(SBMLElement elementToAnnotate) throws SQLException, AnnotationException;

protected void statusReport(String text, Object element) {
for (var o : observers) {
o.update(new ProgressUpdate(text, element, ReportType.STATUS));
}
}

protected void diffReport(String elementType, Object element1, Object element2) {
for (var o : observers) {
o.update(new ProgressUpdate(elementType, List.of(element1, element2), ReportType.DATA));
}
}
public List<ProgressObserver> getObservers() {
return observers;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package edu.ucsd.sbrg.annotation;

public class AnnotationException extends Exception{

public AnnotationException(String msg, Exception e) {
super(msg, e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.ucsd.sbrg.db.bigg.BiGGId;
import org.sbml.jsbml.Reaction;

import java.sql.SQLException;
import java.util.*;

import static edu.ucsd.sbrg.db.adb.AnnotateDBContract.Constants.BIGG_REACTION;
Expand All @@ -17,15 +18,19 @@ public ADBReactionsAnnotator(AnnotateDB adb, ADBAnnotationParameters parameters)
}

@Override
public void annotate(List<Reaction> reactions) {
reactions.forEach(this::annotate);
public void annotate(List<Reaction> reactions) throws SQLException {
for (Reaction reaction : reactions) {
annotate(reaction);
}
}

@Override
public void annotate(Reaction reaction) {
public void annotate(Reaction reaction) throws SQLException {
String id = reaction.getId();
Optional<BiGGId> reactionId = BiGGId.createReactionId(id);
reactionId.ifPresent(biGGId -> addBQB_IS_AnnotationsFromADB(reaction.getAnnotation(), BIGG_REACTION, biGGId));
if (reactionId.isPresent()) {
addBQB_IS_AnnotationsFromADB(reaction.getAnnotation(), BIGG_REACTION, reactionId.get());
}
if ((reaction.getCVTermCount() > 0) && !reaction.isSetMetaId()) {
reaction.setMetaId(reaction.getId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
import org.sbml.jsbml.Model;
import org.sbml.jsbml.SBMLDocument;

import java.sql.SQLException;

public class ADBSBMLAnnotator extends AbstractADBAnnotator<SBMLDocument> {

public ADBSBMLAnnotator(AnnotateDB adb, ADBAnnotationParameters parameters) {
super(adb, parameters);
}

@Override
public void annotate(SBMLDocument doc) {
public void annotate(SBMLDocument doc) throws SQLException {
Model model = doc.getModel();

new ADBSpeciesAnnotator(adb, parameters).annotate(model.getListOfSpecies());
Expand Down
Loading

0 comments on commit 83610f1

Please sign in to comment.