/*******************************************************************************
* Copyright (c) 2008 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cambridge Semantics Incorporated
*******************************************************************************/
package org.openanzo.client.cli;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.lang.ObjectUtils;
import org.openanzo.client.AnzoClient;
import org.openanzo.client.ClientGraph;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.AnzoRuntimeException;
import org.openanzo.ontologies.system.JastorGeneration;
import org.openanzo.ontologies.system.JastorOntology;
import org.openanzo.ontologies.system.SystemFactory;
import org.openanzo.rdf.Dataset;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.NamedGraph;
import org.openanzo.rdf.RDFFormat;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.jastor.JastorContext;
import org.openanzo.rdf.jastor.JastorGenerator;
import org.openanzo.rdf.utils.Pair;
import org.openanzo.rdf.utils.ReadWriteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* Generates Java classes for
*
* @author Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>)
*
*/
class GenCommand extends RdfIOCommand {
private static final Logger log = LoggerFactory.getLogger(GenCommand.class);
private static final Option BASE = new Option("b", "base", true, "Set the base URI of the input RDF file(s) or URI(s)");
private static final Option INPUT_FORMAT = new Option("i", "input-format", true, "Overide the default RDF format associated with the RDF input(s)");
private static final Option GEN_INPUT_OPTION = new Option("f", "gen-input", true, "Generate code based on the given input file, overrides all other options");
private static final Option PACKAGE_OPTION = new Option("k", "package", true, "Generate code into the given package");
private static final Option DESTDIR_OPTION = new Option("d", "destdir", true, "Generate code into the given directory");
private static final Option ENCODING = new Option("e", "encoding", true, "Override the default charset for uploading RDF files.");
static {
BASE.setArgName("URI");
INPUT_FORMAT.setArgName("format");
GEN_INPUT_OPTION.setArgName("file | URI");
PACKAGE_OPTION.setArgName("package");
DESTDIR_OPTION.setArgName("destdir");
}
public String getName() {
return "gen";
}
public Options getOptions() {
Options options = new Options();
options.addOption(BASE);
options.addOption(INPUT_FORMAT);
options.addOption(GEN_INPUT_OPTION);
options.addOption(PACKAGE_OPTION);
options.addOption(DESTDIR_OPTION);
options.addOption(ENCODING);
return options;
}
public int invoke(CommandLine cl, CommandContext context, AnzoClient client) throws AnzoException {
boolean owns = false;
try {
owns = !client.isConnected();
if (owns) {
client.connect();
printOnConnectionSuccess(context);
}
String[] args = cl.getArgs();
RDFFormat inputOverrideFormat = getFormatOption(cl, INPUT_FORMAT);
URI base = getURIOption(cl, BASE, context);
String charsetName = getEncodingOption(cl, ENCODING);
if (cl.hasOption(GEN_INPUT_OPTION.getOpt())) {
RdfInputArgument input = getRdfInputOption(context, cl, GEN_INPUT_OPTION, null, charsetName);
return gen(context, client, input, new OutputStreamWriter(System.out), base);
}
if (!cl.hasOption(PACKAGE_OPTION.getOpt())) {
throw new InvalidArgumentException(PACKAGE_OPTION.getLongOpt() + " option must be specified");
}
if (!cl.hasOption(DESTDIR_OPTION.getOpt())) {
throw new InvalidArgumentException(DESTDIR_OPTION.getLongOpt() + " option must be specified");
}
String pkg = cl.getOptionValue(PACKAGE_OPTION.getOpt());
String destdir = cl.getOptionValue(DESTDIR_OPTION.getOpt());
if (args.length < 1) {
throw new InvalidArgumentException("At least one ontology must be specified");
}
List<INamedGraph> ontGraphs = new ArrayList<INamedGraph>();
for (int i = 0; i < args.length; i++) {
if (!new File(args[i]).exists() && (context.isURI(args[i]) || context.isCURIE(args[i]))) {
try {
URI uri = context.getURI(args[i]);
ClientGraph graph = client.getServerGraph(uri);
ontGraphs.add(graph);
} catch (URISyntaxException e) {
throw new InvalidArgumentException("URI Syntax Exception: " + args[i] + "\n" + e.getMessage());
}
} else {
Pair<File, RDFFormat> file = getFileArgument(context, args[i], inputOverrideFormat, true);
if (!file.second.supportsNamedGraphs()) {
try {
i++;
URI graphUri = context.getURI(args[i]);
INamedGraph ontGraph = new NamedGraph(graphUri);
ReadWriteUtils.loadGraph(ontGraph, file.first);
ontGraphs.add(ontGraph);
} catch (URISyntaxException e) {
throw new InvalidArgumentException("URI Syntax Exception: " + args[i] + "\n" + e.getMessage());
}
} else {
IDataset dataset = new Dataset();
try {
ReadWriteUtils.loadQuadStore(dataset, file.first);
if (dataset.getNamedGraphUris().size() > 1) {
throw new IllegalArgumentException("Ontology file may contain only a single graph: " + file.first);
}
ontGraphs.add(dataset.getNamedGraph(dataset.getNamedGraphUris().iterator().next()));
} catch (Exception e) {
throw new IllegalArgumentException("Could not load ontology file: " + file.first);
}
}
}
}
JastorContext ctx = new JastorContext();
for (INamedGraph ontGraph : ontGraphs) {
ctx.addOntologyToGenerate(ontGraph, ontGraph.getNamedGraphUri().toString(), pkg);
}
JastorGenerator gen = new JastorGenerator(new File(destdir), ctx);
gen.run();
} finally {
try {
if (owns) {
client.close();
}
} catch (AnzoRuntimeException e) {
log.error("Error closing connection", e);
}
}
return 0;
}
private int gen(CommandContext context, AnzoClient client, RdfInputArgument input, Writer output, URI base) throws AnzoException {
int result = 1;
try {
IDataset storeIn = new Dataset();
Reader in = input.getReader();
RDFFormat inputFormat = input.getFormat();
if (base == null) {
base = input.getDefaultGraphURI();
}
ReadWriteUtils.loadQuadStore(storeIn, in, inputFormat, ObjectUtils.toString(base));
for (JastorGeneration gen : SystemFactory.getAllJastorGeneration(storeIn)) {
JastorContext ctx = new JastorContext();
if (gen.getGenerateListeners() != null && gen.getGenerateListeners()) {
ctx.setGenerateListeners(true);
} else {
ctx.setGenerateListeners(false);
}
for (JastorOntology ont : gen.getJastorOntology()) {
if (!client.namedGraphExists(ont.getOntologyUri())) {
context.writeError("Ontology does not exist: " + ont.getOntologyUri());
}
ClientGraph ontGraph = client.getReplicaGraph(ont.getOntologyUri());
if (ont.getGenerate()) {
ctx.addOntologyToGenerate(ontGraph, ont.getOntologyUri().toString(), ont.get_package());
} else {
ctx.addOntologyDependency(ontGraph, ont.getOntologyUri().toString(), ont.get_package());
}
}
JastorGenerator generator = new JastorGenerator(new File(gen.getDestDir()).getCanonicalFile(), ctx);
generator.run();
}
result = 0;
} catch (IOException e) {
log.error("Error generating classes", e);
}
return result;
}
public void printHelp(IConsole consoleWriter) {
String header = "Generates code for the ontologies as supplied by the input RDF or arguments. If arguments are used, a list of ontology URIs or files must be supplied. If an ontology file does to support graphs, a graph URI must be insterted next in the argument list.";
String syntax = "anzo gen [options] [ONTOLOGY-FILE-OR-URI1] [[ONTOLOGY-GRAPH-URI1]] ... [ONTOLOGY-FILE-OR-URIn]";
String footer = "RDF format options are: " + CommandLineInterface.getRDFFormatOptionsString();
Options options = getOptions();
CommandLineInterface.appendGlobalOptions(options);
consoleWriter.printHelp( syntax, header, options, footer);
}
}