diff --git a/README.md b/README.md index fb25474..68f6f0e 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,25 @@ More information at [OpenAPI Specification | Swagger](https://swagger.io/specifi ### OWL The W3C Web Ontology Language (OWL) is a Semantic Web language designed to represent rich and complex knowledge about things, groups of things, and relations between things. OWL is a computational logic-based language such that knowledge expressed in **OWL can be exploited by computer programs**, e.g., to verify the consistency of that knowledge or to make implicit knowledge explicit. OWL documents, known as ontologies, can be published in the World Wide Web + +## Features +- [x] Generate an OpenAPI specification from multiple ontologies (OWL). + - [x] Convert to OWL Classes to OpenAPI schemas. + - [x] Create paths (GET, POST, DELETE, PUT) for each schema. + - [x] Read an OpenAPI base file with the description, documentation and servers of the API. +- [x] Generate a Python server ready to use: + - [x] Use [OpenAPITools/openapi-generator](https://github.com/OpenAPITools/openapi-generator/) to generate the Python server. + - [x] Automatically, generate the controller code (methods) using [Mustache Template](https://github.com/OpenAPITools/openapi-generator/wiki/Mustache-Template-Variables) + - [x] Use authentication using Firebase. + - The user can read any graph. + - The user can write his/her graph. + - [x] Run the queries (these are SPARQL queries are autogenerated): + - [x] Get a resource from any graph (e.g., `GET /models/id`) + - [x] Get all the resources with a specified type from any graph. (e.g., `GET /models`) + - [x] Delete a resource from his/her graph. (e.g., `DELETE /models/id`) + - [x] Create (POST) a resource from his/her graph. (e.g., `POST /models`) + - [x] Update (PUT) a resource from his/her graph. (e.g., `PUT /models/id`) + - [ ] Get a resource related to another resource from any graph (e.g., `GET /models/id/parameters`) + - [x] Obtain the results from the endpoint as JSON or JSON/LD. +- [x] Selected the paths to be created + \ No newline at end of file diff --git a/config.yaml b/config.yaml index a062c44..52901d4 100644 --- a/config.yaml +++ b/config.yaml @@ -10,3 +10,21 @@ ontologies: name: modelcatalog output_dir: outputs openapi_base: modelcatalog_info.yaml + +endpoint: + url: http://endpoint.mint.isi.edu/modelCatalog-1.2.0 + prefix: https://w3id.org/okn/i/mint/ + graph_base: http://ontosoft.isi.edu:3030/modelCatalog-1.2.0/data/ + +firebase: + key: + +relations: + ModelConfiguration: + - predicate: hasInput + path: inputs + - predicate: hasOutput + path: outputs + Setup: + - predicate: hasInput + path: inputs diff --git a/src/main/java/edu/isi/oba/Mapper.java b/src/main/java/edu/isi/oba/Mapper.java index fe04c8d..b8069ef 100644 --- a/src/main/java/edu/isi/oba/Mapper.java +++ b/src/main/java/edu/isi/oba/Mapper.java @@ -1,14 +1,12 @@ package edu.isi.oba; +import edu.isi.oba.config.RelationConfig; import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.XML; import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.model.*; -import org.semanticweb.owlapi.reasoner.OWLReasoner; -import org.semanticweb.owlapi.reasoner.OWLReasonerFactory; -import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory; import org.semanticweb.owlapi.util.DefaultPrefixManager; import java.io.IOException; @@ -24,14 +22,18 @@ class Mapper { public String ont_prefix; List selected_paths; - public Mapper(String ont_url, String ont_prefix, Map prefixes, List paths) throws OWLOntologyCreationException, IOException { + public Mapper(String ont_url, String ont_prefix, Map prefixes, + List paths, Map> relations) + throws OWLOntologyCreationException, IOException { OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); OWLOntology ontology = manager.loadOntology(IRI.create(ont_url)); OWLDocumentFormat format = manager.getOntologyFormat(ontology); this.selected_paths = paths; this.ont_prefix = ont_prefix; setPrefixes(format, prefixes); - schemas = this.createSchemas(ontology); + schemas = this.createSchemas(ontology, relations); + + } /** @@ -56,9 +58,10 @@ private void setPrefixes(OWLDocumentFormat format, Map prefixes) * The schemas includes the properties * * @param ontology Represents an OWL 2 ontology + * @param relations * @return schemas */ - private Map createSchemas(OWLOntology ontology) { + private Map createSchemas(OWLOntology ontology, Map> relations) { Set classes; classes = ontology. getClassesInSignature(); Map schemas = new HashMap<>(); @@ -92,6 +95,14 @@ private Map createSchemas(OWLOntology ontology) { Schema schema = mapperSchema.getSchema(); schemas.put(schema.getName(), schema); + + //obtain the relations +// List model_relations = relations.get(mapperSchema.name); +// for (RelationConfig model_relation : model_relations){ +// add_path_relation(pathGenerator, model_relation.getSubject(), model_relation.getPredicate(), model_relation.getPath()); +// } + + if (this.selected_paths == null){ add_path(pathGenerator, mapperSchema); } else { @@ -134,4 +145,10 @@ private void add_path(Path pathGenerator, MapperSchema mapperSchema) { this.paths.addPathItem(singular_name, pathGenerator.generate_singular(mapperSchema.name)); } + private void add_path_relation(Path pathGenerator, String schema_name, String predicate, String path) { + String relation = "/" + schema_name.toLowerCase() + "s/{id}/" + path; + this.paths.addPathItem(relation, pathGenerator.generate_plural(schema_name)); + + } + } diff --git a/src/main/java/edu/isi/oba/Oba.java b/src/main/java/edu/isi/oba/Oba.java index b74c6ad..05fd1e6 100644 --- a/src/main/java/edu/isi/oba/Oba.java +++ b/src/main/java/edu/isi/oba/Oba.java @@ -1,5 +1,8 @@ package edu.isi.oba; +import edu.isi.oba.config.OntologyConfig; +import edu.isi.oba.config.RelationConfig; +import edu.isi.oba.config.YamlConfig; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.parser.OpenAPIV3Parser; import org.apache.commons.io.FileUtils; @@ -8,83 +11,102 @@ import org.yaml.snakeyaml.constructor.Constructor; import java.io.*; -import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; + import org.apache.commons.cli.*; class Oba { public static void main(String[] args) throws Exception { - Options options = new Options(); - Option input = new Option("c", "config", true, "configuration file path"); - input.setRequired(true); - options.addOption(input); - - - CommandLineParser parser = new DefaultParser(); - HelpFormatter formatter = new HelpFormatter(); - CommandLine cmd; - String config_yaml = null; - - - try { - cmd = parser.parse(options, args); - config_yaml = cmd.getOptionValue("config"); - } catch (ParseException e) { - System.out.println(e.getMessage()); - formatter.printHelp("utility-name", options); - System.exit(1); - } - Constructor constructor = new Constructor(YamlConfig.class); - Yaml yaml = new Yaml( constructor ); - - InputStream config_input = null; - try { - config_input = new FileInputStream(new File(config_yaml)); - } catch (FileNotFoundException e) { - System.err.println("Configuration file not found: " + config_yaml); - } - YamlConfig data = yaml.loadAs( config_input, YamlConfig.class ); - - OpenAPI openapi_base = new OpenAPIV3Parser().read(data.getOpenapi_base()); - + //parse command line + String config_yaml = get_config_yaml(args); + //read the config yaml from command line + YamlConfig data = get_yaml_data(config_yaml); + //read ontologies and get schema and paths + List mappers = get_mappers(data); + //get base of openapi + OpenAPI openapi_base = new OpenAPIV3Parser().read(data.getOpenapi_base()); + //obtain the output directory to write the openapi specification + String dir = data.getOutput_dir() + File.separator + data.getName(); + //write the openapi specification + generate_openapi_spec(openapi_base, mappers, dir); + } - Map ontologies = data.getOntologies(); - List mappers = new ArrayList<>(); - List paths = data.getPaths(); - String dir = data.getOutput_dir() + File.separator + data.getName() ; + private static List get_mappers(YamlConfig data) throws OWLOntologyCreationException, IOException { + Map ontologies = data.getOntologies(); + List mappers = new ArrayList<>(); + List paths = data.getPaths(); + Map> relations = data.getRelations(); + for (Map.Entry entry : ontologies.entrySet()) { + OntologyConfig ontology = entry.getValue(); + Mapper mapper = extract_info(ontology.getXmlUrl(), ontology.getPrefix(), ontology.getPrefixUri(), paths, relations); + mappers.add(mapper); + } + return mappers; + } - for (Map.Entry entry : ontologies.entrySet()) { - OntologyConfig ontology = entry.getValue(); - Mapper mapper = extract_info(ontology.getXmlUrl(), ontology.getPrefix(), ontology.getPrefixUri(), paths); - mappers.add(mapper); - } - String fileName = dir; - Path destinationProject = Paths.get(fileName); - Path baseProject = Paths.get("./tools/base_project/"); - if (Files.exists(destinationProject)){ - System.err.println("The destination project exists"); - } - FileUtils.copyDirectory(baseProject.toFile(), destinationProject.toFile()); - Serializer serializer = new Serializer(mappers, destinationProject, openapi_base); + private static void generate_openapi_spec(OpenAPI openapi_base, List mappers, String dir) throws IOException { + String fileName = dir; + Path destinationProject = Paths.get(fileName); + Path baseProject = Paths.get("./tools/base_project/"); + if (Files.exists(destinationProject)) { + System.err.println("The destination project exists"); + } + FileUtils.copyDirectory(baseProject.toFile(), destinationProject.toFile()); + Serializer serializer = new Serializer(mappers, destinationProject, openapi_base); + + Path destinationQueries = Paths.get(destinationProject + "/.openapi-generator/template/static_files/queries/"); + Path sourceQueries = Paths.get("queries"); + FileUtils.copyDirectory(sourceQueries.toFile(), destinationQueries.toFile()); + } - Path destinationQueries = Paths.get(destinationProject + "/.openapi-generator/template/static_files/queries/"); - Path sourceQueries = Paths.get("queries"); - FileUtils.copyDirectory(sourceQueries.toFile(), destinationQueries.toFile()); + private static YamlConfig get_yaml_data(String config_yaml) { + Constructor constructor = new Constructor(YamlConfig.class); + Yaml yaml = new Yaml(constructor); + + InputStream config_input = null; + try { + config_input = new FileInputStream(new File(config_yaml)); + } catch (FileNotFoundException e) { + System.err.println("Configuration file not found: " + config_yaml); + } + //Yaml config parse + return yaml.loadAs(config_input, YamlConfig.class); + } + private static String get_config_yaml(String[] args) { + //obtain the options to pass configuration + Options options = new Options(); + Option input = new Option("c", "config", true, "configuration file path"); + input.setRequired(true); + options.addOption(input); + + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + CommandLine cmd; + String config_yaml = null; + + try { + cmd = parser.parse(options, args); + config_yaml = cmd.getOptionValue("config"); + } catch (ParseException e) { + System.out.println(e.getMessage()); + formatter.printHelp("utility-name", options); + System.exit(1); + } + return config_yaml; } - public static Mapper extract_info(String ont_serialization_url, String ont_prefix, String ont_uri, List paths) throws OWLOntologyCreationException, IOException { - Map prefixes = new HashMap<>(); - prefixes.put(ont_prefix, ont_uri); - return new Mapper(ont_serialization_url, ont_prefix, prefixes, paths); - } + public static Mapper extract_info(String ont_serialization_url, String ont_prefix, String ont_uri, List paths, Map> relations) throws OWLOntologyCreationException, IOException { + Map prefixes = new HashMap<>(); + prefixes.put(ont_prefix, ont_uri); + return new Mapper(ont_serialization_url, ont_prefix, prefixes, paths, relations); + } } diff --git a/src/main/java/edu/isi/oba/Path.java b/src/main/java/edu/isi/oba/Path.java index bb7567e..3bd819f 100644 --- a/src/main/java/edu/isi/oba/Path.java +++ b/src/main/java/edu/isi/oba/Path.java @@ -40,6 +40,7 @@ public PathItem generate_plural(String schemaName){ } + public PathItem user_login() { List parameters = new ArrayList<>(); ApiResponses apiResponses = new ApiResponses(); diff --git a/src/main/java/edu/isi/oba/config/EndpointConfig.java b/src/main/java/edu/isi/oba/config/EndpointConfig.java new file mode 100644 index 0000000..9bb0240 --- /dev/null +++ b/src/main/java/edu/isi/oba/config/EndpointConfig.java @@ -0,0 +1,31 @@ +package edu.isi.oba.config; + +public class EndpointConfig { + public String url; + public String prefix; + public String graph_base; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getGraph_base() { + return graph_base; + } + + public void setGraph_base(String graph_base) { + this.graph_base = graph_base; + } +} diff --git a/src/main/java/edu/isi/oba/config/FirebaseConfig.java b/src/main/java/edu/isi/oba/config/FirebaseConfig.java new file mode 100644 index 0000000..c42260b --- /dev/null +++ b/src/main/java/edu/isi/oba/config/FirebaseConfig.java @@ -0,0 +1,14 @@ +package edu.isi.oba.config; + +public class FirebaseConfig { + private String key; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } +} + diff --git a/src/main/java/edu/isi/oba/OntologyConfig.java b/src/main/java/edu/isi/oba/config/OntologyConfig.java similarity index 94% rename from src/main/java/edu/isi/oba/OntologyConfig.java rename to src/main/java/edu/isi/oba/config/OntologyConfig.java index 757a5b1..ce15dfe 100644 --- a/src/main/java/edu/isi/oba/OntologyConfig.java +++ b/src/main/java/edu/isi/oba/config/OntologyConfig.java @@ -1,7 +1,8 @@ -package edu.isi.oba; +package edu.isi.oba.config; import java.util.List; + public class OntologyConfig { private String xmlUrl; private String prefix; @@ -32,3 +33,4 @@ public void setPrefixUri(String prefixUri) { } } + diff --git a/src/main/java/edu/isi/oba/config/RelationConfig.java b/src/main/java/edu/isi/oba/config/RelationConfig.java new file mode 100644 index 0000000..c15c258 --- /dev/null +++ b/src/main/java/edu/isi/oba/config/RelationConfig.java @@ -0,0 +1,33 @@ +package edu.isi.oba.config; + +public class RelationConfig { + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPredicate() { + return predicate; + } + + public void setPredicate(String predicate) { + this.predicate = predicate; + } + + private String subject; + private String path; + private String predicate; + + +} diff --git a/src/main/java/edu/isi/oba/YamlConfig.java b/src/main/java/edu/isi/oba/config/YamlConfig.java similarity index 51% rename from src/main/java/edu/isi/oba/YamlConfig.java rename to src/main/java/edu/isi/oba/config/YamlConfig.java index 49ea86a..c4b8d70 100644 --- a/src/main/java/edu/isi/oba/YamlConfig.java +++ b/src/main/java/edu/isi/oba/config/YamlConfig.java @@ -1,13 +1,22 @@ -package edu.isi.oba; +package edu.isi.oba.config; import java.util.List; import java.util.Map; -class YamlConfig { - public Map ontologies; + +public class YamlConfig { + String DEFAULT_OUTPUT_DIRECTORY = "outputs"; + String DEFAULT_PROJECT_NAME = "default_project"; + + public String output_dir = DEFAULT_OUTPUT_DIRECTORY; + public String name = DEFAULT_PROJECT_NAME; + public String openapi_base; public List paths; - public String name = "server"; + public Map ontologies; + public EndpointConfig endpoint; + public FirebaseConfig firebase; + public Map> relations; public String getOutput_dir() { return output_dir; @@ -17,12 +26,13 @@ public void setOutput_dir(String output_dir) { this.output_dir = output_dir; } - public String output_dir = "outputs"; - - - + public String getName() { + return name; + } - public String openapi_base; + public void setName(String name) { + this.name = name; + } public String getOpenapi_base() { return openapi_base; @@ -32,14 +42,6 @@ public void setOpenapi_base(String openapi_base) { this.openapi_base = openapi_base; } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - public List getPaths() { return paths; } @@ -56,11 +58,28 @@ public void setOntologies(Map ontologies) { this.ontologies = ontologies; } - @Override - public String toString() { - return "YamlConfig{" + - "ontologies=" + ontologies + - '}'; + public EndpointConfig getEndpoint() { + return endpoint; + } + + public void setEndpoint(EndpointConfig endpoint) { + this.endpoint = endpoint; + } + + public FirebaseConfig getFirebase() { + return firebase; + } + + public void setFirebase(FirebaseConfig firebase) { + this.firebase = firebase; + } + + public Map> getRelations() { + return relations; + } + + public void setRelations(Map> relations) { + this.relations = relations; } }