Skip to content

Commit

Permalink
Merge pull request #81 from julesjacobsen/master
Browse files Browse the repository at this point in the history
Add obographs-cli
  • Loading branch information
julesjacobsen authored Apr 29, 2022
2 parents 1a892a8 + c45b56e commit f10fa43
Show file tree
Hide file tree
Showing 8 changed files with 419 additions and 4 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[![Build Status](https://travis-ci.org/geneontology/obographs.svg?branch=master)](https://travis-ci.org/geneontology/obographs)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.geneontology/obographs/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.geneontology/obographs)
[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.geneontology/obographs/badge.svg)](http://www.javadoc.io/doc/org.geneontology/obographs)

[![Build Status](https://travis-ci.com/geneontology/obographs.svg?branch=master)](https://app.travis-ci.com/github/geneontology/obographs)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.geneontology.obographs/obographs/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.geneontology.obographs/obographs)
[![javadoc](https://javadoc.io/badge2/org.geneontology.obographs/obographs-core/javadoc.svg)](https://javadoc.io/doc/org.geneontology.obographs/obographs-core)
# OBO Graphs : Developer-friendly graph-oriented ontology JSON/YAML

This repo contains both a specification for a JSON/YAML format for
Expand Down
133 changes: 133 additions & 0 deletions obographs-cli/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>obographs</artifactId>
<groupId>org.geneontology.obographs</groupId>
<version>0.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>obographs-cli</artifactId>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.geneontology.obographs</groupId>
<artifactId>obographs-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.geneontology.obographs</groupId>
<artifactId>obographs-owlapi</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
<excludes>
<exclude>**/application*.yml</exclude>
<exclude>**/application*.yaml</exclude>
<exclude>**/application*.properties</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>org.geneontology.obographs.cli.OboGraphs</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<propertiesEncoding>${project.build.sourceEncoding}</propertiesEncoding>
<delimiters>
<delimiter>${resource.delimiter}</delimiter>
</delimiters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>module-info.class</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>4.6.3</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Aproject=${project.groupId}/${project.artifactId}</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.geneontology.obographs.cli;

import org.geneontology.obographs.cli.commands.Convert;
import org.geneontology.obographs.cli.commands.ManifestVersionProvider;
import org.geneontology.obographs.cli.commands.Validate;
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;

import static picocli.CommandLine.Command;
import static picocli.CommandLine.Spec;

@Command(name = "obographs",
versionProvider = ManifestVersionProvider.class,
mixinStandardHelpOptions = true,
description = "OBO Graphs: Developer-friendly graph-oriented ontology in JSON/YAML",
subcommands = {
Convert.class,
Validate.class,
}
)
public class OboGraphs implements Runnable {

@Spec
CommandSpec spec;

@Override
public void run() {
// if the command was invoked without subcommand, show the usage help
spec.commandLine().usage(System.err);
}

public static void main(String[] args) {
System.exit(new CommandLine(new OboGraphs()).execute(args));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.geneontology.obographs.cli.commands;

import org.geneontology.obographs.core.io.OgJsonGenerator;
import org.geneontology.obographs.core.io.OgYamlGenerator;
import org.geneontology.obographs.core.model.GraphDocument;
import org.geneontology.obographs.owlapi.FromOwl;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import picocli.CommandLine.Command;

import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.concurrent.Callable;

import static picocli.CommandLine.Option;
import static picocli.CommandLine.Parameters;

@Command(name = "convert", description = "converts OWL to obographs JSON")
public class Convert implements Callable<Integer> {

// obographs convert *.owl -o .
// obographs convert owl/*.owl -o obographs/. -f all
// obographs convert *.owl -o . -f json
@Parameters(arity = "1..*", paramLabel = "FILE", description = "OWL/OBO file(s) to process.")
private List<Path> inputPaths;

@Option(names = {"-o", "--out-dir"}, description = "Output directory for converted files (defaults to input directory).")
Path outDir;

@Option(names = {"-f", "--format"}, paramLabel = "<format>", description = {
"Output format for obograph files.",
"The format parameter is optional (defaults to `all`), and is used to specify the output format(s) of converted files.",
"The possible options are:",
" * @|yellow json|@ - Write to JSON.",
" * @|yellow yaml|@ - Write to YAML.",
" * @|yellow all|@ - Write both JSON and YAML."
})
Format outFormat = Format.all;

enum Format {json, yaml, all}

@Override
public Integer call() {
if (outDir != null) {
try {
createDirectoryIfNotPresent(outDir);
} catch (IOException ex) {
System.err.println("Output " + outDir + " must be a writeable directory!");
return 1;
}
}
List<Format> formats = parseFormats(outFormat);
OWLOntologyManager owlOntologyManager = OWLManager.createOWLOntologyManager();
FromOwl fromOwl = new FromOwl();
int exitCode = 0;
for (Path inputFile : inputPaths) {
try {
System.err.println("Reading " + inputFile);
OWLOntology owlOntology = owlOntologyManager.loadOntologyFromOntologyDocument(inputFile.toFile());
GraphDocument graphDocument = fromOwl.generateGraphDocument(owlOntology);
for (Format format : formats) {
Path outFile = outFile(inputFile, format);
if (format == Format.json) {
OgJsonGenerator.write(outFile.toFile(), graphDocument);
}
if (format == Format.yaml) {
OgYamlGenerator.write(outFile.toFile(), graphDocument);
}
System.err.println("Written " + outFile.toAbsolutePath());
}
} catch (Exception e) {
System.err.println(e.getMessage());
exitCode = 1;
}
}
return exitCode;
}

private List<Format> parseFormats(Format format) {
if (format == Format.json) {
return List.of(Format.json);
} else if (format == Format.yaml) {
return List.of(Format.yaml);
}
return List.of(Format.json, Format.yaml);
}

private Path outFile(Path inputFile, Format format) {
String outFileName = outFileName(inputFile, format);
if (outDir == null) {
return inputFile.toAbsolutePath().getParent().resolve(outFileName);
}
return outDir.resolve(outFileName);
}

private String outFileName(Path inputFile, Format format) {
String fileName = inputFile.getFileName().toString();
if (fileName.endsWith(".obo")) {
return fileName.replace(".obo", "." + format);
} else if (fileName.endsWith(".owl")) {
return fileName.replace(".owl", "." + format);
}
throw new IllegalArgumentException("Input file " + inputFile + " must be in OWL or OBO format");
}

private Path createDirectoryIfNotPresent(Path dir) throws IOException {
try {
return Files.createDirectory(dir);
} catch (FileAlreadyExistsException x) {
if (!Files.isDirectory(dir, LinkOption.NOFOLLOW_LINKS)) {
throw new NotDirectoryException("Not a directory: " + dir);
}
}
return dir;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.geneontology.obographs.cli.commands;

import picocli.CommandLine;
import picocli.CommandLine.IVersionProvider;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
* {@link IVersionProvider} implementation that returns version information from the obographs-cli-x.x.jar file's {@code /META-INF/MANIFEST.MF} file.
* Requires building with maven-jar-plugin using the manifest.addDefaultImplementationEntries=true option.
*
* Adapted from https://github.com/remkop/picocli/blob/main/picocli-examples/src/main/java/picocli/examples/VersionProviderDemo2.java.
*/
public class ManifestVersionProvider implements IVersionProvider {

private static final String MAVEN_ARTIFACT_ID = "obographs-cli";

public String[] getVersion() throws Exception {
Enumeration<URL> resources = CommandLine.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try {
Manifest manifest = new Manifest(url.openStream());
// This is the Maven ${project.name} generated from the artifactId in the project pom.xml
if (isApplicableManifest(manifest, MAVEN_ARTIFACT_ID)) {
Attributes attr = manifest.getMainAttributes();
var version = (String) get(attr, "Implementation-Version");
return new String[]{MAVEN_ARTIFACT_ID + " version \"" + version + "\""};
}
} catch (IOException ex) {
return new String[]{"Unable to read from " + url + ": " + ex};
}
}
return new String[0];
}

private boolean isApplicableManifest(Manifest manifest, String mavenArtifactId) {
Attributes attributes = manifest.getMainAttributes();
return mavenArtifactId.equals(get(attributes, "Implementation-Title"));
}

private static Object get(Attributes attributes, String key) {
return attributes.get(new Attributes.Name(key));
}
}
Loading

0 comments on commit f10fa43

Please sign in to comment.