Skip to content

Commit

Permalink
Merge pull request #6 from plantbreeding/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
daveneti authored Jun 22, 2024
2 parents 1600b20 + 27d88a7 commit b9544ae
Show file tree
Hide file tree
Showing 127 changed files with 6,152 additions and 941 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
# brapi-schema-tools
Tools used to manipulate, extend, convert, and modify the BrAPI Specification documents
Tools used to manipulate, extend, convert, and modify the BrAPI Specification documents.

Only the [Java based tools](java/README.md) are available at the moment.

These consist of a Command Line Interface (CLI) that can generate OpenAPI Specification or
GraphQL Schema from the BrAPI JSON Schema.

## BrAPI JSON Schema
The BrAPI JSON Schema is a new way to define the Data and Query model for BrAPI using JSON Schema.

The approach is experimental, but it is likely to be supported in a future release of BrAPI.
PLease go to the 'data-model-separation' branch of BrAPI to see the JSON Schema.
* https://github.com/plantbreeding/BrAPI/tree/data-model-separation/Specification/BrAPI-Schema
34 changes: 29 additions & 5 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
# BrAPI Schema Tools
# BrAPI Schema Tools - Java

BrAPI Schema Tools generates and view the BrAPI Specification
The Java BrAPI Schema Tools generates OpenAPI Specification or GraphQL Schema generation.
There is also a basic spring application that allow you to view the BrAPI Specification.

Here you find the following modules
## Quick Start

1. Download the Command Line Interface (CLI) from the
[Releases](https://github.com/plantbreeding/brapi-schema-tools/releases) page
2. Run the application on your terminal
* In windows

```powershell
BrAPITools
```
* In Linux or macOS
```shell
BrAPITools
```
## For developers
For more control over the OpenAPI Specification or GraphQL Schema generation or to
contribute, please contact the developers by creating a
[GitHub issue](https://github.com/plantbreeding/brapi-schema-tools/issues) or look directly at the
code
The Java BrAPI Schema Tools consists of 4 modules:
* [application](application/README.md) - A spring application that allow you to view the generated specification
* buildSrc- Defines the plugins use by the gradle
* buildSrc - Defines the plugins use by the gradle
* [cli](cli/README.md) - The command line tool that makes use of the core module
* [core](core/README.md) - The core schema tools
* [core](core/README.md) - The core schema tools for OpenAPI Specification or GraphQL Schema generation
3 changes: 2 additions & 1 deletion java/application/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
management.endpoints.web.exposure.include=health,metrics,info
spring.graphql.schema.printer.enabled=true
spring.graphql.graphiql.enabled=true
spring.graphql.graphiql.enabled=true
server.port=8081
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void outputIntrospectionSchema(GraphQLSchema schema) {
}

private void printGraphQLSchemaErrors(Response<GraphQLSchema> response) {
System.err.println("There were errors generating the GraphQL Schema:");
System.err.printf("There were %d errors generating the GraphQL Schema:%n", response.getAllErrors().size());
response.getAllErrors().forEach(this::printError);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public BrAPISchemaReader() {
*/
public Response<List<BrAPIClass>> readDirectories(Path schemaDirectory) throws BrAPISchemaReaderException {
try {
return dereferenceAndValidate(find(schemaDirectory, 3, this::schemaPathMatcher).flatMap(this::createBrAPISchemas).collect(Response.toList())) ;
return dereferenceAndValidate(find(schemaDirectory, 3, this::schemaPathMatcher).map(this::createBrAPISchemas).collect(Response.mergeLists())) ;
} catch (RuntimeException | IOException e) {
throw new BrAPISchemaReaderException(e);
}
Expand All @@ -85,7 +85,7 @@ public Response<List<BrAPIClass>> readDirectories(Path schemaDirectory) throws B
*/
public Response<BrAPIClass> readSchema(Path schemaPath, String module) throws BrAPISchemaReaderException {
try {
return createBrAPISchemas(schemaPath, module).collect(Response.toList()).mapResult(list -> list.get(0)) ;
return createBrAPISchemas(schemaPath, module).mapResult(list -> list.get(0)) ;
} catch (RuntimeException e) {
throw new BrAPISchemaReaderException(e);
}
Expand All @@ -104,14 +104,13 @@ public Response<BrAPIClass> readSchema(Path schemaPath, String module) throws Br
*/
public Response<BrAPIClass> readSchema(Path path, String schema, String module) throws BrAPISchemaReaderException {
try {
return createBrAPISchemas(path, objectMapper.readTree(schema), module).collect(Response.toList()).mapResult(list -> list.get(0)) ;
return createBrAPISchemas(path, objectMapper.readTree(schema), module).mapResult(list -> list.get(0)) ;
} catch (RuntimeException| JsonProcessingException e) {
throw new BrAPISchemaReaderException(String.format("Can not read schema at '%s' in module '%s' from '%s', due to '%s'", path, module, schema, e.getMessage()), e);
}
}

private Response<List<BrAPIClass>> dereferenceAndValidate(Response<List<BrAPIClass>> types) {

return types.mapResult(this::dereference).mapResultToResponse(this::validate) ;
}

Expand All @@ -123,13 +122,14 @@ private List<BrAPIClass> dereference(List<BrAPIClass> types) {

types.forEach(type -> {
if (type instanceof BrAPIAllOfType brAPIAllOfType) {
brAPIClasses.add(BrAPIObjectType.builder().
name(brAPIAllOfType.getName()).
description(brAPIAllOfType.getDescription()).
module(brAPIAllOfType.getModule()).
properties(extractProperties(new ArrayList<>(), brAPIAllOfType, typeMap)).build()) ;
brAPIClasses.add(BrAPIObjectType.builder()
.name(brAPIAllOfType.getName())
.description(brAPIAllOfType.getDescription())
.module(brAPIAllOfType.getModule())
.metadata(brAPIAllOfType.getMetadata() != null ? brAPIAllOfType.getMetadata().toBuilder().build() : null)
.properties(extractProperties(new ArrayList<>(), brAPIAllOfType, typeMap)).build());
} else {
brAPIClasses.add(type) ;
brAPIClasses.add(type);
}
});

Expand Down Expand Up @@ -210,7 +210,7 @@ private List<BrAPIObjectProperty> extractProperties(List<BrAPIObjectProperty> pr
return properties ;
}

private Stream<Response<BrAPIClass>> createBrAPISchemas(Path path) {
private Response<List<BrAPIClass>> createBrAPISchemas(Path path) {
return createBrAPISchemas(path, findModule(path));
}

Expand All @@ -220,15 +220,19 @@ private String findModule(Path path) {
return module != null && COMMON_MODULES.contains(module) ? null : module;
}

private Stream<Response<BrAPIClass>> createBrAPISchemas(Path path, String module) {
JsonSchema schema = factory.getSchema(path.toUri());
private Response<List<BrAPIClass>> createBrAPISchemas(Path path, String module) {
try {
JsonSchema schema = factory.getSchema(path.toUri());

JsonNode json = schema.getSchemaNode();
JsonNode json = schema.getSchemaNode();

return createBrAPISchemas(path, json, module);
return createBrAPISchemas(path, json, module);
} catch (RuntimeException e) {
return Response.fail(Response.ErrorType.VALIDATION, String.format("Can not read schemas from for module '%s' from path '%s' due to '%s'", module, path, e.getMessage())) ;
}
}

private Stream<Response<BrAPIClass>> createBrAPISchemas(Path path, JsonNode json, String module) {
private Response<List<BrAPIClass>> createBrAPISchemas(Path path, JsonNode json, String module) {
JsonNode defs = json.get("$defs");

if (defs != null) {
Expand All @@ -239,7 +243,7 @@ private Stream<Response<BrAPIClass>> createBrAPISchemas(Path path, JsonNode json

return Stream.generate(() -> null)
.takeWhile(x -> iterator.hasNext())
.map(n -> iterator.next()).map(entry -> createBrAPIClass(path, entry.getValue(), entry.getKey(), module));
.map(n -> iterator.next()).map(entry -> createBrAPIClass(path, entry.getValue(), entry.getKey(), module)).collect(Response.toList());
}

private Response<BrAPIClass> createBrAPIClass(Path path, JsonNode jsonNode, String fallbackName, String module) {
Expand Down Expand Up @@ -379,15 +383,15 @@ private Response<BrAPIType> createObjectType(Path path, JsonNode jsonNode, Strin

List<BrAPIObjectProperty> properties = new ArrayList<>();
return Response.empty().
mapOnCondition(jsonNode.has("additionalProperties"), () -> findChildNode(jsonNode, "additionalProperties", false).
mapOnCondition(jsonNode.has("additionalProperties"), () -> findChildNode(jsonNode, "additionalProperties", true).
mapResultToResponse(additionalPropertiesNode -> createProperty(path, additionalPropertiesNode, "additionalProperties",
module, required.contains("additionalProperties")).onSuccessDoWithResult(properties::add))).
mapOnCondition(jsonNode.has("properties"), () -> findChildNode(jsonNode, "properties", false).
mapOnCondition(jsonNode.has("properties"), () -> findChildNode(jsonNode, "properties", true).
mapResult(JsonNode::fields).
mapResultToResponse(fields -> createProperties(path, fields, module, required)).
onSuccessDoWithResult(properties::addAll)).
onSuccessDo(() -> builder.properties(properties)).
mapOnCondition(jsonNode.has("brapi-metadata"), () -> findChildNode(jsonNode, "brapi-metadata", false).
mapOnCondition(jsonNode.has("brapi-metadata"), () -> findChildNode(jsonNode, "brapi-metadata", true).
mapResultToResponse(this::parseMetadata).onSuccessDoWithResult(builder::metadata)).
map(() -> success(builder.build()));
}
Expand Down Expand Up @@ -441,6 +445,8 @@ private Response<BrAPIType> createAllOfType(Path path, JsonNode jsonNode, String
mapResult(this::childNodes).
mapResultToResponse(childNodes -> childNodes.mapResultToResponse(nodes -> createAllTypes(path, nodes, name, module))).
onSuccessDoWithResult(builder::allTypes).
mapOnCondition(jsonNode.has("brapi-metadata"), () -> findChildNode(jsonNode, "brapi-metadata", true).
mapResultToResponse(this::parseMetadata).onSuccessDoWithResult(builder::metadata)).
map(() -> success(builder.build()));
}

Expand All @@ -464,6 +470,8 @@ private Response<BrAPIType> createOneOfType(Path path, JsonNode jsonNode, String
mapResult(this::childNodes).
mapResultToResponse(childNodes -> childNodes.mapResultToResponse(nodes -> createPossibleTypes(path, nodes, name, module))).
onSuccessDoWithResult(builder::possibleTypes).
mapOnCondition(jsonNode.has("brapi-metadata"), () -> findChildNode(jsonNode, "brapi-metadata", true).
mapResultToResponse(this::parseMetadata).onSuccessDoWithResult(builder::metadata)).
map(() -> success(builder.build()));
}

Expand All @@ -487,6 +495,8 @@ private Response<BrAPIType> createEnumType(JsonNode jsonNode, String name, Strin
return findStringList(jsonNode, "enum", true).
mapResultToResponse(strings -> createEnumValues(strings, type)).
onSuccessDoWithResult(builder::values).
mapOnCondition(jsonNode.has("brapi-metadata"), () -> findChildNode(jsonNode, "brapi-metadata", true).
mapResultToResponse(this::parseMetadata).onSuccessDoWithResult(builder::metadata)).
map(() -> success(builder.build()));
}

Expand Down
Loading

0 comments on commit b9544ae

Please sign in to comment.