/*******************************************************************************
* Copyright (c) 2010-2011 VIVO Harvester Team. For full list of contributors, please see the AUTHORS file provided.
* All rights reserved.
* This program and the accompanying materials are made available under the terms of the new BSD license which accompanies this distribution, and is available at http://www.opensource.org/licenses/bsd-license.html
******************************************************************************/
package org.vivoweb.harvester.translate;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vivoweb.harvester.util.InitLog;
import org.vivoweb.harvester.util.args.ArgDef;
import org.vivoweb.harvester.util.args.ArgList;
import org.vivoweb.harvester.util.args.ArgParser;
import org.vivoweb.harvester.util.args.UsageException;
import org.vivoweb.harvester.util.repo.Record;
import org.vivoweb.harvester.util.repo.RecordHandler;
import com.hp.gloze.Gloze;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
/**
* Gloze Tranlator This class translates XML into its own natural RDF ontology using the gloze library. Translation into
* the VIVO ontology is completed using the RDF Translator. TODO Stephen: Identify additional parameters required for
* translation TODO Stephen: Identify methods to invoke in the gloze library
* @author Stephen V. Williams swilliams@ctrip.ufl.edu
*/
public class GlozeTranslator {
/**
* the log property for logging errors, information, debugging
*/
private static Logger log = LoggerFactory.getLogger(GlozeTranslator.class);
/**
* the file to be translated FIXME Stephen: remove this and use the incoming stream
*/
protected File incomingXMLFile;
/**
* The incoming schema to help gloze translate the xml file
*/
protected File incomingSchema;
/**
* the uri base for relative nodes in the xml file
*/
protected URI uriBase;
/**
* in stream is the stream containing the file (xml) that we are going to translate
*/
private InputStream inStream;
/**
* out stream is the stream that the controller will be handling and were we will dump the translation
*/
private OutputStream outStream;
/**
* record handler for incoming records
*/
protected RecordHandler inStore;
/**
* record handler for storing records
*/
protected RecordHandler outStore;
/**
* Constructor
* @param args commandline arguments
* @throws IOException error parsing options
* @throws UsageException user requested usage message
*/
private GlozeTranslator(String... args) throws IOException, UsageException {
this(getParser().parse(args));
}
/**
* @param argList <ul>
* <li><em>inRecordHandler</em> the incoming record handler when record handlers are due</li>
* <li><em>schema</em> the incoming schema for gloze translation</li>
* <li><em>outRecordHandler</em> the out record handler</li>
* <li><em>uriBase</em> required for gloze translation the unset URIBASE used is
* http://vivoweb.org/glozeTranslation/noURI/</li>
* </ul>
* @throws IOException error connecting to record handlers
*/
private GlozeTranslator(ArgList argList) throws IOException {
this(
argList.get("u"),
argList.get("z"),
RecordHandler.parseConfig(argList.get("i"), argList.getValueMap("I")),
RecordHandler.parseConfig(argList.get("o"), argList.getValueMap("O"))
);
}
/**
* Constructor
* @param uriBase the base for all URIs generated
* @param xmlSchema the xml schema for gloze to use while translating
* @param inStore the input recordhandler
* @param outStore the output recordhandler
*/
public GlozeTranslator(String uriBase, String xmlSchema, RecordHandler inStore, RecordHandler outStore) {
if(uriBase == null) {
throw new IllegalArgumentException("Must provide a uri base");
}
setURIBase(uriBase);
if(xmlSchema == null) {
throw new IllegalArgumentException("Must provide a xml schema");
}
setIncomingSchema(new File(xmlSchema));//FIXME: use FileAide and Streams!
if(inStore == null) {
throw new IllegalArgumentException("Must provide an input recordhandler");
}
this.inStore = inStore;
if(outStore == null) {
throw new IllegalArgumentException("Must provide an output recordhandler");
}
this.outStore = outStore;
}
/**
* Setter for xmlFile
* @param xmlFile the file to translate
*/
public void setIncomingXMLFile(File xmlFile) {
this.incomingXMLFile = xmlFile;
}
/**
* Setter for schema
* @param schema the schema that gloze can use, but doesn't need to translate the xml
*/
public void setIncomingSchema(File schema) {
this.incomingSchema = schema;
}
/**
* Setter for uriBase
* @param base the base uri to apply to all relative entities
*/
public void setURIBase(String base) {
try {
this.uriBase = new URI(base);
} catch(URISyntaxException e) {
throw new IllegalArgumentException(e);
}
}
/**
* The main translation method for the gloze translation class setups up the necessary conditions for using the
* gloze library then executes its translation class
*/
public void translateFile() {
Gloze gl = new Gloze();
Model outputModel = ModelFactory.createDefaultModel();
try {
// Create a temporary file to use for translation
File tempFile = new File("temp");
FileOutputStream tempWrite = new FileOutputStream(tempFile);
while(true) {
int bytedata = this.inStream.read();
if(bytedata == -1) {
break;
}
tempWrite.write(bytedata);
}
this.inStream.close();
tempWrite.close();
gl.xml_to_rdf(tempFile, this.incomingSchema, this.uriBase, outputModel);
tempFile.delete();
} catch(Exception e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
}
outputModel.write(this.outStream);
}
/***
*
*/
public void execute() {
if((this.uriBase != null) && (this.inStream != null)) {
try {
// create a output stream for writing to the out store
ByteArrayOutputStream buff = new ByteArrayOutputStream();
// get from the in record and translate
for(Record r : this.inStore) {
if(r.needsProcessed(this.getClass())) {
this.inStream = new ByteArrayInputStream(r.getData().getBytes());
this.outStream = buff;
translateFile();
buff.flush();
this.outStore.addRecord(r.getID(), buff.toString(), this.getClass());
r.setProcessed(this.getClass());
buff.reset();
}
}
buff.close();
} catch(Exception e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
}
} else {
log.error("Invalid Arguments: Gloze Translation requires a URIBase and XMLFile");
throw new IllegalArgumentException();
}
}
/**
* Get the ArgParser for this task
* @return the ArgParser
*/
protected static ArgParser getParser() {
ArgParser parser = new ArgParser("GlozeTranslator");
parser.addArgument(new ArgDef().setShortOption('i').setLongOpt("input").withParameter(true, "CONFIG_FILE").setDescription("config file for input record handler").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('I').setLongOpt("inputOverride").withParameterValueMap("RH_PARAM", "VALUE").setDescription("override the RH_PARAM of input record handler config using VALUE").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('o').setLongOpt("output").withParameter(true, "CONFIG_FILE").setDescription("config file for output record handler").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('O').setLongOpt("outputOverride").withParameterValueMap("RH_PARAM", "VALUE").setDescription("override the RH_PARAM of output record handler config using VALUE").setRequired(false));
parser.addArgument(new ArgDef().setShortOption('z').setLongOpt("xmlSchema").withParameter(false, "XML_SCHEMA").setDescription("xsl file").setRequired(true));
parser.addArgument(new ArgDef().setShortOption('u').setLongOpt("uriBase").withParameter(false, "URI_BASE").setDescription("uri base").setRequired(true));
return parser;
}
/**
* Main Method
* @param args list of arguments required to execute glozetranslate
*/
public static void main(String... args) {
Exception error = null;
try {
InitLog.initLogger(args, getParser());
log.info(getParser().getAppName() + ": Start");
new GlozeTranslator(args).execute();
} catch(IllegalArgumentException e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
System.out.println(getParser().getUsage());
error = e;
} catch(UsageException e) {
log.info("Printing Usage:");
System.out.println(getParser().getUsage());
error = e;
} catch(Exception e) {
log.error(e.getMessage());
log.debug("Stacktrace:",e);
error = e;
} finally {
log.info(getParser().getAppName() + ": End");
if(error != null) {
System.exit(1);
}
}
}
}