org.openprovenance.prov.interop.InteropFramework Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of prov-interop Show documentation
Show all versions of prov-interop Show documentation
A package aimed at systematic testing convertibility of prov representations.
package org.openprovenance.prov.interop;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Variant;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.openprovenance.prov.model.*;
import org.openprovenance.prov.interop.Formats.ProvFormat;
import org.openprovenance.prov.interop.Formats.ProvFormatType;
import org.openprovenance.prov.model.exception.DocumentedUnsupportedCaseException;
import org.openprovenance.prov.rules.Rules;
import org.openprovenance.prov.template.compiler.BindingsBeanGenerator;
import org.openprovenance.prov.template.compiler.ConfigProcessor;
import org.openprovenance.prov.template.compiler.configuration.Locations;
import org.openprovenance.prov.template.compiler.configuration.TemplatesProjectConfiguration;
import org.openprovenance.prov.template.expander.Expand;
import org.openprovenance.prov.generator.GeneratorDetails;
import org.openprovenance.prov.generator.GraphGenerator;
import org.openprovenance.prov.template.json.Bindings;
import static org.openprovenance.prov.interop.Formats.ProvFormat.*;
/**
* The interoperability framework for PROV, with utility methods to write and read documents to files and streams,
* according to media types, format (specified as {@link ProvFormat}). The class also provides helper functions to support content
* negotiation.
*
*
*
* @author lavm, dtm
*
*/
public class InteropFramework implements InteropMediaType, org.openprovenance.prov.model.ProvDocumentWriter, Framework{
public final static String configFile="config.interop.properties";
public final static String configuration;
public final static String factoryClass;
public final static ProvFactory defaultFactory;
static {
Properties properties=Framework.getPropertiesFromClasspath(configFile);
configuration=(String)properties.get("interop.config");
factoryClass = properties.getProperty("prov.factory");
defaultFactory= dynamicallyLoadFactory(factoryClass);
}
static ProvFactory dynamicallyLoadFactory(String factory) {
Class> clazz=null;
try {
clazz = Class.forName(factory);
Method method=clazz.getMethod("getFactory");
return (ProvFactory) method.invoke(new Object[0]);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private final Outputer outputer;
private final Inputer inputer;
static public ProvFactory getDefaultFactory(){
return defaultFactory;
}
public ProvFactory getFactory(){
return defaultFactory;
}
static Logger logger = LogManager.getLogger(InteropFramework.class);
public static final String UNKNOWN = "unknown";
final ProvFactory pFactory;
private final Hashtable extensionMap;
public final Hashtable extensionRevMap;
private final Hashtable mimeTypeMap;
public final Hashtable mimeTypeRevMap;
private final Hashtable provTypeMap;
final private CommandLineArguments config;
final private Map deserializerMap;
final private Map deserializerMap2;
/** Default constructor for the ProvToolbox interoperability framework.
* It uses the factory declared in the configuration file as its default factory.
*/
public InteropFramework() {
this(new CommandLineArguments(), defaultFactory);
}
public InteropFramework(ProvFactory pFactory) {
this(new CommandLineArguments(),pFactory);
}
public InteropFramework(CommandLineArguments config,
ProvFactory pFactory) {
this.pFactory=pFactory;
this.config=config;
extensionMap = new Hashtable<>();
extensionRevMap = new Hashtable<>();
mimeTypeMap = new Hashtable<>();
mimeTypeRevMap = new Hashtable<>();
provTypeMap = new Hashtable<>();
initializeExtensionMap(extensionMap, extensionRevMap);
this.outputer = new Outputer(this, pFactory);
this.inputer = new Inputer(this, pFactory);
this.deserializerMap=this.inputer.deserializerMap;
this.deserializerMap2=this.inputer.deserializerMap2;
}
public CommandLineArguments getConfig() {
return config;
}
/**
* Create a list of mime types supported by ProvToolbox in view of constructing an Accept Header.
* @return a string representing the mime types.
*/
public String buildAcceptHeader() {
StringBuilder mimetypes = new StringBuilder();
Enumeration e = mimeTypeMap.keys();
String sep = "";
while (e.hasMoreElements()) {
ProvFormat f = e.nextElement();
if (isInputFormat(f)) {
// careful - cant use .hasMoreElements as we are filtering
mimetypes.append(sep);
sep = ",";
mimetypes.append(mimeTypeMap.get(f));
}
}
mimetypes.append(sep);
mimetypes.append("*/*;q=0.1"); // be liberal
return mimetypes.toString();
}
/**
* A method to connect to a URL and follow redirects if any.
* @param theURL a URL to connect to
* @return a {@link URLConnection}
* @throws IOException if connection cannot be opened and no response is received.
*/
public URLConnection connectWithRedirect(URL theURL) throws IOException {
URLConnection conn = null;
String accept_header = buildAcceptHeader();
int redirect_count = 0;
boolean done = false;
while (!done) {
if (theURL.getProtocol().equals("file")) {
return null;
}
boolean isHttp = (theURL.getProtocol().equals("http") || theURL
.getProtocol().equals("https"));
logger.debug("Requesting: " + theURL);
conn = theURL.openConnection();
if (isHttp) {
logger.debug("Accept: " + accept_header);
conn.setRequestProperty("Accept", accept_header);
}
conn.setConnectTimeout(60000);
conn.setReadTimeout(60000);
conn.connect();
done = true; // by default quit after one request
if (isHttp) {
logger.debug("Response: " + conn.getHeaderField(0));
int rc = ((HttpURLConnection) conn).getResponseCode();
if ((rc == HttpURLConnection.HTTP_MOVED_PERM)
|| (rc == HttpURLConnection.HTTP_MOVED_TEMP)
|| (rc == HttpURLConnection.HTTP_SEE_OTHER)
|| (rc == 307)) {
if (redirect_count > 10) {
return null; // Error: too many redirects
}
redirect_count++;
String loc = conn.getHeaderField("Location");
if (loc != null) {
theURL = new URL(loc);
done = false;
} else {
return null; // Bad redirect
}
} else if ((rc < 200) || (rc >= 300)) {
return null; // Unsuccessful
}
}
}
return conn;
}
/**Maps an file extension to a Media type
* @param extension the extension of a file containing a serialization of PROV
* @return a String for the Internet Media type corresponding to a file with this extension
*/
public String convertExtensionToMediaType(String extension) {
ProvFormat format = extensionRevMap.get(extension);
if (format == null)
return null;
return mimeTypeMap.get(format);
}
/** Returns an extension for a given type of serialization of PROV
* @param format {@link ProvFormat} for which file extension is sought
* @return a String for the extension of a file containing such a serialization
*/
public String getExtension(ProvFormat format) {
String extension = UNKNOWN;
if (format != null) {
extension = extensionMap.get(format);
}
return extension;
}
/**
* Returns an option at given index in an array of options, or null
* @param options an array of Strings
* @param index position of the option that is sought
* @return the option or null
*/
String getOption(String[] options, int index) {
if ((options != null) && (options.length > index)) {
return options[index];
}
return null;
}
/**
* Get a {@link ProvFormat} given the file's exetension
* @param filename the file for which the {@link ProvFormat} is sought
* @return a {@link ProvFormat}
*/
public ProvFormat getTypeForFile(String filename) {
int count = filename.lastIndexOf(".");
if (count == -1)
return null;
String extension = filename.substring(count + 1);
return extensionRevMap.get(extension);
}
/**
* Get a {@link ProvFormat} given a format string
* @param format the format for which the {@link ProvFormat} is sought
* @return a {@link ProvFormat}
*/
public ProvFormat getTypeForFormat(String format) {
ProvFormat result;
// try as mimetype and then as an extension
result = mimeTypeRevMap.get(format);
if (result == null)
result = extensionRevMap.get(format);
return result;
}
/**
* Support for content negotiation, jax-rs style. Create a list of media
* type supported by the framework.
* @see Content Negotiation
* @return a list of {@link Variant}
*/
public List getVariants() {
List vs = new ArrayList<>();
for (Map.Entry entry : mimeTypeRevMap.entrySet()) {
if (isOutputFormat(entry.getValue())) {
String[] parts = entry.getKey().split("/");
MediaType m = new MediaType(parts[0], parts[1]);
vs.add(new Variant(m, (java.util.Locale) null, null));
}
}
return vs;
}
/** Initialization function
* @param extensionMap mapping of {@link ProvFormat} to extensions
* @param extensionRevMap reverse mapping of extensions to {@link ProvFormat}
*/
public void initializeExtensionMap(Hashtable extensionMap,
Hashtable extensionRevMap) {
for (ProvFormat f : ProvFormat.values()) {
switch (f) {
case DOT:
extensionMap.put(ProvFormat.DOT, EXTENSION_DOT);
extensionRevMap.put(EXTENSION_DOT, ProvFormat.DOT);
extensionRevMap.put("gv", ProvFormat.DOT);
mimeTypeMap.put(ProvFormat.DOT, MEDIA_TEXT_VND_GRAPHVIZ);
mimeTypeRevMap.put(MEDIA_TEXT_VND_GRAPHVIZ, ProvFormat.DOT);
provTypeMap.put(ProvFormat.DOT, ProvFormatType.OUTPUT);
break;
case JPEG:
extensionMap.put(ProvFormat.JPEG, EXTENSION_JPG);
extensionRevMap.put(EXTENSION_JPEG, ProvFormat.JPEG);
extensionRevMap.put(EXTENSION_JPG, ProvFormat.JPEG);
mimeTypeMap.put(ProvFormat.JPEG, MEDIA_IMAGE_JPEG);
mimeTypeRevMap.put(MEDIA_IMAGE_JPEG, ProvFormat.JPEG);
provTypeMap.put(ProvFormat.JPEG, ProvFormatType.OUTPUT);
break;
case PNG:
extensionMap.put(ProvFormat.PNG, EXTENSION_PNG);
extensionRevMap.put(EXTENSION_PNG, ProvFormat.PNG);
mimeTypeMap.put(ProvFormat.PNG, MEDIA_IMAGE_PNG);
mimeTypeRevMap.put(MEDIA_IMAGE_PNG, ProvFormat.PNG);
provTypeMap.put(ProvFormat.PNG, ProvFormatType.OUTPUT);
break;
case JSON:
extensionMap.put(ProvFormat.JSON, EXTENSION_JSON);
extensionRevMap.put(EXTENSION_JSON, ProvFormat.JSON);
mimeTypeMap.put(ProvFormat.JSON, MediaType.APPLICATION_JSON);
mimeTypeRevMap.put(MediaType.APPLICATION_JSON, ProvFormat.JSON);
provTypeMap.put(ProvFormat.JSON, ProvFormatType.INPUTOUTPUT);
break;
case PDF:
extensionMap.put(ProvFormat.PDF, EXTENSION_PDF);
extensionRevMap.put(EXTENSION_PDF, ProvFormat.PDF);
mimeTypeMap.put(ProvFormat.PDF, MEDIA_APPLICATION_PDF);
mimeTypeRevMap.put(MEDIA_APPLICATION_PDF, ProvFormat.PDF);
provTypeMap.put(ProvFormat.PDF, ProvFormatType.OUTPUT);
break;
case PROVN:
extensionMap.put(PROVN, EXTENSION_PROVN);
extensionRevMap.put(EXTENSION_PROVN, PROVN);
extensionRevMap.put("pn", PROVN);
extensionRevMap.put("asn", PROVN);
extensionRevMap.put("prov-asn", PROVN);
mimeTypeMap.put(PROVN,
MEDIA_TEXT_PROVENANCE_NOTATION);
mimeTypeRevMap.put(MEDIA_TEXT_PROVENANCE_NOTATION,
PROVN);
provTypeMap.put(PROVN, ProvFormatType.INPUTOUTPUT);
break;
case SVG:
extensionMap.put(ProvFormat.SVG, EXTENSION_SVG);
extensionRevMap.put(EXTENSION_SVG, ProvFormat.SVG);
mimeTypeMap.put(ProvFormat.SVG, MEDIA_IMAGE_SVG_XML);
mimeTypeRevMap.put(MEDIA_IMAGE_SVG_XML, ProvFormat.SVG);
provTypeMap.put(ProvFormat.SVG, ProvFormatType.OUTPUT);
break;
case TRIG:
extensionMap.put(ProvFormat.TRIG, EXTENSION_TRIG);
extensionRevMap.put(EXTENSION_TRIG, ProvFormat.TRIG);
mimeTypeMap.put(ProvFormat.TRIG, MEDIA_APPLICATION_TRIG);
mimeTypeRevMap.put(MEDIA_APPLICATION_TRIG, ProvFormat.TRIG);
provTypeMap.put(ProvFormat.TRIG, ProvFormatType.INPUTOUTPUT);
break;
case TURTLE:
extensionMap.put(ProvFormat.TURTLE, EXTENSION_TTL);
extensionRevMap.put(EXTENSION_TTL, ProvFormat.TURTLE);
mimeTypeMap.put(ProvFormat.TURTLE, MEDIA_TEXT_TURTLE);
mimeTypeRevMap.put(MEDIA_TEXT_TURTLE, ProvFormat.TURTLE);
provTypeMap.put(ProvFormat.TURTLE, ProvFormatType.INPUTOUTPUT);
break;
case JSONLD:
extensionMap.put(ProvFormat.JSONLD, EXTENSION_JSONLD);
extensionRevMap.put(EXTENSION_JSONLD, ProvFormat.JSONLD);
mimeTypeMap.put(ProvFormat.JSONLD, MEDIA_APPLICATION_JSONLD);
mimeTypeRevMap.put(MEDIA_APPLICATION_JSONLD, ProvFormat.JSONLD);
provTypeMap.put(ProvFormat.JSONLD, ProvFormatType.INPUTOUTPUT);
break;
case PROVX:
extensionMap.put(ProvFormat.PROVX, EXTENSION_PROVX);
extensionRevMap.put(EXTENSION_PROVX, ProvFormat.PROVX);
extensionRevMap.put(EXTENSION_XML, ProvFormat.PROVX);
mimeTypeMap.put(ProvFormat.PROVX, MEDIA_APPLICATION_PROVENANCE_XML);
mimeTypeRevMap.put(MEDIA_APPLICATION_PROVENANCE_XML, ProvFormat.PROVX);
provTypeMap.put(ProvFormat.PROVX, ProvFormatType.INPUTOUTPUT);
break;
default:
break;
}
}
}
/**
* Determines whether this format received as argument is an input format.
* @param format a {@link ProvFormat}
* @return true if format is an input format
*/
public Boolean isInputFormat(ProvFormat format) {
ProvFormatType t = provTypeMap.get(format);
return (t.equals(ProvFormatType.INPUT) ||
t.equals(ProvFormatType.INPUTOUTPUT));
}
/**
* Determines whether this format received as argument is an output format.
* @param format a {@link ProvFormat}
* @return true if format is an output format
*/
public Boolean isOutputFormat(ProvFormat format) {
ProvFormatType t = provTypeMap.get(format);
return (t.equals(ProvFormatType.OUTPUT) ||
t.equals(ProvFormatType.INPUTOUTPUT));
}
public List