From ae94cb46809df32e83edd77d58bf473f747ee0dc Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Fri, 7 Jun 2024 14:53:59 +1200 Subject: [PATCH 1/9] updated version --- .../src/main/groovy/brapi.schema-tools.java-conventions.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle b/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle index 01b8dcc..2553f0b 100644 --- a/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle +++ b/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle @@ -3,7 +3,7 @@ plugins { } group = 'org.brapi' -version = '0.0.1' +version = '0.1.0' sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 From ff7b20bb04a5f967fb74e2315e37b54a56c038fa Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Fri, 7 Jun 2024 14:59:06 +1200 Subject: [PATCH 2/9] removed property --- java/core/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/core/build.gradle b/java/core/build.gradle index 44b88b0..53f22d8 100644 --- a/java/core/build.gradle +++ b/java/core/build.gradle @@ -79,9 +79,6 @@ project.plugins.withType(MavenPublishPlugin).all { description = name url = "https://github.com/plantbreeding/brapi-schema-tools" autoReleaseAfterClose = true - properties = [ - autoReleaseAfterClose: true - ] licenses { license { name = "MIT License" From a110f11ff4d116754f02464eeaebcbb54d93d53b Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Fri, 7 Jun 2024 15:09:38 +1200 Subject: [PATCH 3/9] removed property --- java/core/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/core/build.gradle b/java/core/build.gradle index 53f22d8..b0ced59 100644 --- a/java/core/build.gradle +++ b/java/core/build.gradle @@ -78,7 +78,9 @@ project.plugins.withType(MavenPublishPlugin).all { name = "${project.group}:${project.name}" description = name url = "https://github.com/plantbreeding/brapi-schema-tools" - autoReleaseAfterClose = true + properties = [ + autoReleaseAfterClose: true + ] licenses { license { name = "MIT License" From 852fa23b1bf76c5f6f61c60b3efe549fcfee9c7f Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Fri, 7 Jun 2024 18:12:00 +1200 Subject: [PATCH 4/9] improve javadocs --- .../core/brapischema/BrAPISchemaReaderException.java | 3 +++ .../core/graphql/metadata/GraphQLGeneratorMetadata.java | 3 +++ .../core/graphql/options/GraphQLGeneratorOptions.java | 2 ++ .../java/org/brapi/schematools/core/model/BrAPIAllOfType.java | 3 +++ .../core/openapi/options/OpenAPIGeneratorOptions.java | 2 ++ 5 files changed, 13 insertions(+) diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java index ba4d4e9..622e622 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java @@ -1,5 +1,8 @@ package org.brapi.schematools.core.brapischema; +/** + * Exception thrown during the reading of BrAPI JSON Schema + */ public class BrAPISchemaReaderException extends Exception { public BrAPISchemaReaderException(Exception e) { super(e); diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/metadata/GraphQLGeneratorMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/metadata/GraphQLGeneratorMetadata.java index 3a4e7d5..81fefa3 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/metadata/GraphQLGeneratorMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/metadata/GraphQLGeneratorMetadata.java @@ -3,6 +3,9 @@ import lombok.Getter; import lombok.Setter; +/** + * Provides metadata for the GraphQL generation + */ @Getter @Setter public class GraphQLGeneratorMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java index 7ef1989..f46d4dc 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java @@ -86,4 +86,6 @@ public boolean isGeneratingMutationType() { public boolean isUsingIDType() { return ids != null && ids.isUsingIDType(); } + + public static class GraphQLGeneratorOptionsBuilder{} } \ No newline at end of file diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIAllOfType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIAllOfType.java index c8ffda0..51c4198 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIAllOfType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIAllOfType.java @@ -5,6 +5,9 @@ import java.util.List; +/** + * Represents a type that takes all of properties from the wrapped types + */ @Builder(toBuilder = true) @Value public class BrAPIAllOfType implements BrAPIClass { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java index a26775a..2fb2236 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java @@ -206,4 +206,6 @@ public String getPluralFor(String name) { public String getSingularForProperty(String name) { return toSingular(name) ; } + + public static class OpenAPIGeneratorOptionsBuilder {} } From d7df75135ff756ea5a54ed90faefbdd66cd24efd Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Fri, 7 Jun 2024 18:43:52 +1200 Subject: [PATCH 5/9] removed properties again --- java/core/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/core/build.gradle b/java/core/build.gradle index b0ced59..1677dbf 100644 --- a/java/core/build.gradle +++ b/java/core/build.gradle @@ -78,9 +78,6 @@ project.plugins.withType(MavenPublishPlugin).all { name = "${project.group}:${project.name}" description = name url = "https://github.com/plantbreeding/brapi-schema-tools" - properties = [ - autoReleaseAfterClose: true - ] licenses { license { name = "MIT License" From 73e2bc172a577991113ba5764aecdc70f8f514d2 Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Mon, 10 Jun 2024 19:43:27 +1200 Subject: [PATCH 6/9] Updated java docs --- .../core/brapischema/BrAPISchemaReader.java | 6 + .../BrAPISchemaReaderException.java | 11 +- .../core/graphql/GraphQLGenerator.java | 33 +- .../options/GraphQLGeneratorOptions.java | 63 ++- .../core/graphql/options/IdsOptions.java | 3 + .../graphql/options/ListQueryOptions.java | 8 + .../graphql/options/MutationTypeOptions.java | 8 + .../graphql/options/QueryTypeOptions.java | 3 + .../graphql/options/SearchQueryOptions.java | 8 + .../graphql/options/SingleQueryOptions.java | 8 + .../core/model/BrAPIArrayType.java | 3 + .../schematools/core/model/BrAPIClass.java | 19 + .../schematools/core/model/BrAPIEnumType.java | 3 + .../core/model/BrAPIEnumValue.java | 3 + .../schematools/core/model/BrAPIMetadata.java | 3 + .../core/model/BrAPIObjectProperty.java | 3 + .../core/model/BrAPIObjectType.java | 3 + .../core/model/BrAPIOneOfType.java | 3 + .../core/model/BrAPIPrimitiveType.java | 16 + .../core/model/BrAPIReferenceType.java | 3 + .../schematools/core/model/BrAPIType.java | 7 + .../openapi/OpenAPIComponentsException.java | 14 +- .../core/openapi/OpenAPIComponentsReader.java | 10 + .../core/openapi/OpenAPIGenerator.java | 39 +- .../core/openapi/metadata/DeleteMetadata.java | 4 + .../openapi/metadata/ListGetMetadata.java | 3 + .../metadata/OpenAPIGeneratorMetadata.java | 3 + .../core/openapi/metadata/PostMetadata.java | 3 + .../core/openapi/metadata/PutMetadata.java | 3 + .../core/openapi/metadata/SearchMetadata.java | 3 + .../openapi/metadata/SingleGetMetadata.java | 3 + .../core/openapi/options/DeleteOptions.java | 8 + .../core/openapi/options/IdsOptions.java | 9 + .../core/openapi/options/ListGetOptions.java | 8 + .../options/OpenAPIGeneratorOptions.java | 201 +++++++- .../core/openapi/options/PostOptions.java | 8 + .../core/openapi/options/PutOptions.java | 8 + .../core/openapi/options/SearchOptions.java | 8 + .../openapi/options/SingleGetOptions.java | 8 + .../schematools/core/response/Response.java | 468 ++++++++++++++++-- .../response/ResponseFailedException.java | 6 + .../schematools/core/utils/StringUtils.java | 3 + 42 files changed, 991 insertions(+), 46 deletions(-) diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java index a9ce74e..82ceba3 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java @@ -37,6 +37,9 @@ import static org.brapi.schematools.core.response.Response.fail; import static org.brapi.schematools.core.response.Response.success; +/** + * Utility class for reading BrAPI JSON Schema. + */ @AllArgsConstructor public class BrAPISchemaReader { private static final Pattern REF_PATTERN = Pattern.compile("((?:\\.{1,2}+/)*(?:[\\w-]+\\/)*(?:\\w+).json)?#\\/\\$defs\\/(\\w+)"); @@ -45,6 +48,9 @@ public class BrAPISchemaReader { private final JsonSchemaFactory factory; private final ObjectMapper objectMapper; + /** + * Creates schema reader with a basic {@link ObjectMapper} and V202012 JSonSchema version + */ public BrAPISchemaReader() { factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012); objectMapper = new ObjectMapper(); diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java index 622e622..7ade7e3 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java @@ -4,7 +4,14 @@ * Exception thrown during the reading of BrAPI JSON Schema */ public class BrAPISchemaReaderException extends Exception { - public BrAPISchemaReaderException(Exception e) { - super(e); + /** Constructs a new exception with the specified cause and a detail message of + * (cause==null ? null : cause.toString()) (which typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than wrappers for other throwables + * (for example, java.security.PrivilegedActionException). + * @param cause the cause (which is saved for later retrieval by the {@link #getCause} method). + * (A null value is permitted, and indicates that the cause is nonexistent or unknown.) + */ + public BrAPISchemaReaderException(Exception cause) { + super(cause) ; } } diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java index a75c3f4..dbf588f 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java @@ -34,24 +34,55 @@ import static org.brapi.schematools.core.utils.StringUtils.toPlural; import static org.brapi.schematools.core.utils.StringUtils.toSentenceCase; +/** + * Generates a GraphQL schema from a BrAPI Json Schema. + */ @AllArgsConstructor public class GraphQLGenerator { private final BrAPISchemaReader schemaReader; private final GraphQLGeneratorOptions options; + /** + * Creates a GraphQLGenerator using a default {@link BrAPISchemaReader} and + * the default {@link GraphQLGeneratorOptions}. + */ public GraphQLGenerator() { this(new BrAPISchemaReader(), GraphQLGeneratorOptions.load()) ; } + /** + * Creates a GraphQLGenerator using a default {@link BrAPISchemaReader} and + * the provided {@link GraphQLGeneratorOptions}. + * @param options The options to be used in the generation. + */ public GraphQLGenerator(GraphQLGeneratorOptions options) { this(new BrAPISchemaReader(), options) ; } + /** + * Generates the {@link GraphQLSchema} from the complete BrAPI Specification in + * a directory contains a subdirectories for each module that contain + * the BrAPI Json schema and the additional subdirectories called 'Requests' + * that contains the request schemas and BrAPI-Common that contains common schemas + * for use across modules. + * @param schemaDirectory the path to the complete BrAPI Specification + * @return the {@link GraphQLSchema} from the complete BrAPI Specification + */ public Response generate(Path schemaDirectory) { return generate(schemaDirectory, new GraphQLGeneratorMetadata()) ; } + /** + * Generates the {@link GraphQLSchema} from the complete BrAPI Specification in + * a directory contains a subdirectories for each module that contain + * the BrAPI Json schema and the additional subdirectories called 'Requests' + * that contains the request schemas and BrAPI-Common that contains common schemas + * for use across modules. + * @param schemaDirectory the path to the complete BrAPI Specification + * @param metadata additional metadata that is used in the generation + * @return the {@link GraphQLSchema} from the complete BrAPI Specification + */ public Response generate(Path schemaDirectory, GraphQLGeneratorMetadata metadata) { try { @@ -62,7 +93,7 @@ public Response generate(Path schemaDirectory, GraphQLGeneratorMe } @Getter - public static class Generator { + private static class Generator { private final GraphQLGeneratorOptions options; private final GraphQLGeneratorMetadata metadata; private final Map brAPISchemas; diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java index f46d4dc..58e6ee3 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/GraphQLGeneratorOptions.java @@ -4,13 +4,18 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import graphql.schema.GraphQLScalarType; import lombok.*; +import org.brapi.schematools.core.graphql.GraphQLGenerator; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; +/** + * Options for the {@link GraphQLGenerator}. + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder(toBuilder = true) @@ -22,10 +27,21 @@ public class GraphQLGeneratorOptions { MutationTypeOptions mutationType; IdsOptions ids; + /** + * Load the options from an options file in YAML or Json. The options file may have missing + * (defined) values, in these cases the default values are loaded. See {@link #load()} + * @param optionsFile The path to the options file in YAML or Json. + * @return The options loaded from the YAML or Json file. + * @throws IOException if the options file can not be found or is incorrectly formatted. + */ public static GraphQLGeneratorOptions load(Path optionsFile) throws IOException { return load(Files.newInputStream(optionsFile)); } + /** + * Load the default options + * @return The default options + */ public static GraphQLGeneratorOptions load() { try { @@ -38,13 +54,25 @@ public static GraphQLGeneratorOptions load() { } } - private static GraphQLGeneratorOptions load(InputStream inputStream) throws IOException { + /** + * Load the options from an options input stream in YAML or Json. The options file may have missing + * (defined) values, in these cases the default values are loaded. See {@link #load()} + * @param inputStream The input stream in YAML or Json. + * @return The options loaded from input stream. + * @throws IOException if the input stream is not valid or the content is incorrectly formatted. + */ + public static GraphQLGeneratorOptions load(InputStream inputStream) throws IOException { ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); return mapper.readValue(inputStream, GraphQLGeneratorOptions.class); } + /** + * Creates a build class with the default options already loaded. This also for + * ease of overriding programmatically only a few options from their defaults. + * @return a build class with the default options already loaded. + */ public static GraphQLGeneratorOptions.GraphQLGeneratorOptionsBuilder defaultBuilder() { ObjectMapper objectMapper = new ObjectMapper(); try { @@ -57,35 +85,68 @@ public static GraphQLGeneratorOptions.GraphQLGeneratorOptionsBuilder defaultBuil } } + /** + * Determines if the Generator should generate the Query Type. Short-cut for {@link QueryTypeOptions#generating} + * @return true if the Generator should generate the Query Type, false otherwise + */ @JsonIgnore public boolean isGeneratingQueryType() { return queryType != null && queryType.isGenerating(); } + /** + * Determines if the Generator should generate any single query. Returns true if + * {@link SingleQueryOptions#generating} is set to true or + * {@link SingleQueryOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any single query, false otherwise + */ @JsonIgnore public boolean isGeneratingSingleQueries() { return isGeneratingQueryType() && (queryType.getSingleQuery().isGenerating() || queryType.getSingleQuery().getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any list query. Returns true if + * {@link ListQueryOptions#generating} is set to true or + * {@link ListQueryOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any list query, false otherwise + */ @JsonIgnore public boolean isGeneratingListQueries() { return isGeneratingQueryType() && (queryType.getListQuery().isGenerating() || queryType.getListQuery().getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any search query. Returns true if + * {@link SearchQueryOptions#generating} is set to true or + * {@link SearchQueryOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any search query, false otherwise + */ @JsonIgnore public boolean isGeneratingSearchQueries() { return isGeneratingQueryType() && (queryType.getSearchQuery().isGenerating() || queryType.getSearchQuery().getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate the Mutation Type. Short-cut for {@link MutationTypeOptions#generating} + * @return true if the Generator should generate the Mutation Type, false otherwise + */ @JsonIgnore public boolean isGeneratingMutationType() { return mutationType != null && (mutationType.isGenerating() || mutationType.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the built-in GraphQLID type should be used for IDs instead of GraphQLString + * @return true if the built-in GraphQLID type should be used for IDs instead of GraphQLString, false otherwise + */ @JsonIgnore public boolean isUsingIDType() { return ids != null && ids.isUsingIDType(); } + /** + * + */ public static class GraphQLGeneratorOptionsBuilder{} } \ No newline at end of file diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/IdsOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/IdsOptions.java index b0cccde..d14346e 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/IdsOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/IdsOptions.java @@ -3,6 +3,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; +/** + * Provides options for the generation of Ids + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/ListQueryOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/ListQueryOptions.java index 7519706..70d8f44 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/ListQueryOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/ListQueryOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of List Queries + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -37,6 +40,11 @@ public class ListQueryOptions { String pageTypeName; String pageFieldName; + /** + * Determines if the List Query is generated for a specific primary model + * @param name the name of the primary model + * @return true if the List Query is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/MutationTypeOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/MutationTypeOptions.java index 99cc6da..860a2d9 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/MutationTypeOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/MutationTypeOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of the Mutation Type + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class MutationTypeOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Mutation is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Mutation is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/QueryTypeOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/QueryTypeOptions.java index 9d46cdf..b139e3f 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/QueryTypeOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/QueryTypeOptions.java @@ -3,6 +3,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; +/** + * Provides options for the generation of the Query Type + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SearchQueryOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SearchQueryOptions.java index 417978b..8481ce9 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SearchQueryOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SearchQueryOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Search Queries + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class SearchQueryOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Search Query is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Search Query is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SingleQueryOptions.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SingleQueryOptions.java index 04c3bdd..ff28611 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SingleQueryOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/options/SingleQueryOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Single Queries + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -20,6 +23,11 @@ public class SingleQueryOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Single Query is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Single Query is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIArrayType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIArrayType.java index 4d32bbb..21a3234 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIArrayType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIArrayType.java @@ -3,6 +3,9 @@ import lombok.Builder; import lombok.Value; +/** + * Array type that represents an array of items of type {@link #items}. + */ @Builder(toBuilder = true) @Value public class BrAPIArrayType implements BrAPIType { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIClass.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIClass.java index ad174f3..21c052b 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIClass.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIClass.java @@ -1,7 +1,26 @@ package org.brapi.schematools.core.model; +/** + * Interface implemented by types that are output data modules, but are not + * simple scalar types or an array + */ public interface BrAPIClass extends BrAPIType { + + /** + * The class description + * @return The class description + */ String getDescription(); + + /** + * Gets the module to which this class belongs + * @return the module to which this class belongs + */ String getModule(); + + /** + * Gets the metadata associated with this class + * @return the metadata associated with this class + */ BrAPIMetadata getMetadata(); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumType.java index 0154ffa..6a4e836 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumType.java @@ -5,6 +5,9 @@ import java.util.List; +/** + * A BrAPI Class that provides a list of possible {@link #values} of a specific {@link #type}. + */ @Builder(toBuilder = true) @Value public class BrAPIEnumType implements BrAPIClass { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumValue.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumValue.java index 44bf580..9d1cbee 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumValue.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIEnumValue.java @@ -3,6 +3,9 @@ import lombok.Builder; import lombok.Value; +/** + * A value within an enumeration list + */ @Builder(toBuilder = true) @Value public class BrAPIEnumValue { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java index 1b284d2..65c43ae 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java @@ -3,6 +3,9 @@ import lombok.Builder; import lombok.Value; +/** + * The BrAPI metadata associated with a {@link BrAPIClass}. + */ @Builder(toBuilder = true) @Value public class BrAPIMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java index b08d2ce..917407d 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java @@ -3,6 +3,9 @@ import lombok.Builder; import lombok.Value; +/** + * The property definition for a BrAPI Object. + */ @Builder(toBuilder = true) @Value public class BrAPIObjectProperty { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java index d8fe2b6..9c16b80 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java @@ -5,6 +5,9 @@ import java.util.List; +/** + * An Object definition that has {@link #properties} + */ @Builder(toBuilder = true) @Value public class BrAPIObjectType implements BrAPIClass { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIOneOfType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIOneOfType.java index 29d0e6f..0bfe46d 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIOneOfType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIOneOfType.java @@ -5,6 +5,9 @@ import java.util.List; +/** + * A BrAPI Class that represents one and only one {@link #possibleTypes}. + */ @Builder(toBuilder = true) @Value public class BrAPIOneOfType implements BrAPIClass { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIPrimitiveType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIPrimitiveType.java index d20b3ef..523a584 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIPrimitiveType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIPrimitiveType.java @@ -2,12 +2,28 @@ import lombok.Value; +/** + * A scalar or primitive type, which can be one of 4 possible instances: + * {@link #BOOLEAN}, {@link #INTEGER}, {@link #NUMBER}, or {@link #STRING}. + */ @Value public class BrAPIPrimitiveType implements BrAPIType { + /** + * Boolean Primitive Type + */ public static final BrAPIType BOOLEAN = new BrAPIPrimitiveType("boolean"); + /** + * Boolean Integer Type + */ public static final BrAPIType INTEGER = new BrAPIPrimitiveType("integer"); + /** + * Boolean Number Type + */ public static final BrAPIType NUMBER = new BrAPIPrimitiveType("number"); + /** + * Boolean String Type + */ public static final BrAPIType STRING = new BrAPIPrimitiveType("string"); String name; diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIReferenceType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIReferenceType.java index 30b0df5..1e86afe 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIReferenceType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIReferenceType.java @@ -3,6 +3,9 @@ import lombok.Builder; import lombok.Value; +/** + * A reference to another named type with {@link #name}. + */ @Builder(toBuilder = true) @Value public class BrAPIReferenceType implements BrAPIType { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIType.java index 153c7b4..0e8cf4b 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIType.java @@ -1,5 +1,12 @@ package org.brapi.schematools.core.model; +/** + * Base class for all BrAPI Types + */ public interface BrAPIType { + /** + * Gets the name of the BrAPI Type + * @return the name of the BrAPI Type + */ String getName(); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsException.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsException.java index 500da2a..fd47455 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsException.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsException.java @@ -1,7 +1,17 @@ package org.brapi.schematools.core.openapi; +/** + * Exception thrown during the generation of BrAPI OpenAPI Specification + */ public class OpenAPIComponentsException extends Exception { - public OpenAPIComponentsException(Exception exception) { - super(exception); + /** Constructs a new exception with the specified cause and a detail message of + * (cause==null ? null : cause.toString()) (which typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than wrappers for other throwables + * (for example, java.security.PrivilegedActionException). + * @param cause the cause (which is saved for later retrieval by the {@link #getCause} method). + * (A null value is permitted, and indicates that the cause is nonexistent or unknown.) + */ + public OpenAPIComponentsException(Exception cause) { + super(cause); } } diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsReader.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsReader.java index 2bdc59b..b16164b 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsReader.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIComponentsReader.java @@ -11,7 +11,17 @@ import static java.nio.file.Files.find; +/** + * Utility class for reading OpenAPI Components from YAML files. + */ public class OpenAPIComponentsReader { + + /** + * Read OpenAPI Components from YAML files. + * @param schemaDirectory The path to the directory containing the YAML files. + * @return OpenAPI Components read from YAML files. + * @throws OpenAPIComponentsException if there is an problem reading the YAML files. + */ public Components readComponents(Path schemaDirectory) throws OpenAPIComponentsException { Components components = new Components(); diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java index 1d386d9..27760b3 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java @@ -1,5 +1,6 @@ package org.brapi.schematools.core.openapi; +import graphql.schema.GraphQLSchema; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -14,6 +15,7 @@ import lombok.AllArgsConstructor; import org.brapi.schematools.core.brapischema.BrAPISchemaReader; import org.brapi.schematools.core.brapischema.BrAPISchemaReaderException; +import org.brapi.schematools.core.graphql.options.GraphQLGeneratorOptions; import org.brapi.schematools.core.model.*; import org.brapi.schematools.core.openapi.metadata.OpenAPIGeneratorMetadata; import org.brapi.schematools.core.openapi.options.OpenAPIGeneratorOptions; @@ -30,6 +32,9 @@ import static org.brapi.schematools.core.response.Response.success; import static org.brapi.schematools.core.utils.StringUtils.toParameterCase; +/** + * Generates a OpenAPI Specification from a BrAPI Json Schema. + */ @AllArgsConstructor public class OpenAPIGenerator { @@ -37,18 +42,50 @@ public class OpenAPIGenerator { private final OpenAPIComponentsReader componentsReader; private final OpenAPIGeneratorOptions options ; + /** + * Creates a OpenAPIGenerator using a default {@link BrAPISchemaReader} and + * the default {@link OpenAPIGeneratorOptions}. + */ public OpenAPIGenerator() { this(new BrAPISchemaReader(), new OpenAPIComponentsReader(), OpenAPIGeneratorOptions.load()) ; } + /** + * Creates a GraphQLGenerator using a default {@link BrAPISchemaReader} and + * the provided {@link OpenAPIGeneratorOptions}. + * @param options The options to be used in the generation. + */ public OpenAPIGenerator(OpenAPIGeneratorOptions options) { this(new BrAPISchemaReader(), new OpenAPIComponentsReader(), options) ; } + /** + * Generates a list of {@link OpenAPI} from the complete BrAPI Specification in + * a directory contains a subdirectories for each module that contain + * the BrAPI Json schema and the additional subdirectories called 'Requests' + * that contains the request schemas and BrAPI-Common that contains common schemas + * for use across modules. The list will contain a single {@link OpenAPI} or separate {@link OpenAPI} + * for each module. See {@link OpenAPIGeneratorOptions#separatingByModule}. + * @param schemaDirectory the path to the complete BrAPI Specification + * @param componentsDirectory the path to the additional OpenAPI components needed to generate the Specification + * @return a list of {@link OpenAPI} generated from the complete BrAPI Specification + */ public Response> generate(Path schemaDirectory, Path componentsDirectory) { return generate(schemaDirectory, componentsDirectory, new OpenAPIGeneratorMetadata()) ; } + /** + * Generates a list of {@link OpenAPI} from the complete BrAPI Specification in + * a directory contains a subdirectories for each module that contain + * the BrAPI Json schema and the additional subdirectories called 'Requests' + * that contains the request schemas and BrAPI-Common that contains common schemas + * for use across modules. The list will contain a single {@link OpenAPI} or separate {@link OpenAPI} + * for each module. See {@link OpenAPIGeneratorOptions#separatingByModule}. + * @param schemaDirectory the path to the complete BrAPI Specification + * @param componentsDirectory the path to the additional OpenAPI components needed to generate the Specification + * @param metadata additional metadata that is used in the generation + * @return a list of {@link OpenAPI} generated from the complete BrAPI Specification + */ public Response> generate(Path schemaDirectory, Path componentsDirectory, OpenAPIGeneratorMetadata metadata) { try { @@ -58,7 +95,7 @@ public Response> generate(Path schemaDirectory, Path componentsDir } } - public static class Generator { + private static class Generator { private final OpenAPIGeneratorOptions options; private final OpenAPIGeneratorMetadata metadata; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/DeleteMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/DeleteMetadata.java index 068da8d..d47d29d 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/DeleteMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/DeleteMetadata.java @@ -6,6 +6,10 @@ import java.util.HashMap; import java.util.Map; + +/** + * Provides metadata for the Delete endpoints + */ @Getter @Setter public class DeleteMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/ListGetMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/ListGetMetadata.java index e0f09d8..2cf3ae0 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/ListGetMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/ListGetMetadata.java @@ -6,6 +6,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides metadata for the List Get endpoints + */ @Getter @Setter public class ListGetMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/OpenAPIGeneratorMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/OpenAPIGeneratorMetadata.java index 971abc3..8ed3aae 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/OpenAPIGeneratorMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/OpenAPIGeneratorMetadata.java @@ -3,6 +3,9 @@ import lombok.Getter; import lombok.Setter; +/** + * Provides metadata for the OpenAPI generation + */ @Getter @Setter public class OpenAPIGeneratorMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PostMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PostMetadata.java index 4225a7b..84765c4 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PostMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PostMetadata.java @@ -6,6 +6,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides metadata for the Post endpoints + */ @Getter @Setter public class PostMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PutMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PutMetadata.java index 1ea2c2e..14e1e54 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PutMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/PutMetadata.java @@ -6,6 +6,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides metadata for the Put endpoints + */ @Getter @Setter public class PutMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SearchMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SearchMetadata.java index af38a55..c0e96cb 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SearchMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SearchMetadata.java @@ -6,6 +6,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides metadata for the Search Post and Get endpoints + */ @Getter @Setter public class SearchMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SingleGetMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SingleGetMetadata.java index 913fc03..38535a1 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SingleGetMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/metadata/SingleGetMetadata.java @@ -6,6 +6,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides metadata for the Single Get endpoints + */ @Getter @Setter public class SingleGetMetadata { diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/DeleteOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/DeleteOptions.java index 67a9986..2ff5a56 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/DeleteOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/DeleteOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Delete Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class DeleteOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Delete Endpoint is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Delete Endpoint is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/IdsOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/IdsOptions.java index c1f483d..e98904a 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/IdsOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/IdsOptions.java @@ -9,6 +9,9 @@ import static org.brapi.schematools.core.utils.StringUtils.toParameterCase; +/** + * Provides options for the generation of Ids + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,12 @@ public class IdsOptions { @Builder.Default Map parameterFor = new HashMap<>(); + /** + * Gets the id parameter name for a specific primary model. For example the id parameter (or field) + * name of Study, would be 'studyDbiId' by default. Use {@link #parameterFor} to override this value. + * @param name the name of the primary model + * @return id parameter name for a specific primary model + */ @JsonIgnore public String getIDParameterFor(String name) { return parameterFor.getOrDefault(name, String.format(nameFormat, toParameterCase(name))) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/ListGetOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/ListGetOptions.java index c800d77..84c8dd8 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/ListGetOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/ListGetOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of List Get Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class ListGetOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the List Get Endpoint is generated for a specific primary model + * @param name the name of the primary model + * @return true if the List Get Endpoint is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java index 2fb2236..c7711e2 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/OpenAPIGeneratorOptions.java @@ -6,6 +6,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import lombok.*; +import org.brapi.schematools.core.graphql.options.QueryTypeOptions; +import org.brapi.schematools.core.graphql.options.SingleQueryOptions; +import org.brapi.schematools.core.openapi.OpenAPIGenerator; import java.io.IOException; import java.io.InputStream; @@ -18,6 +21,9 @@ import static org.brapi.schematools.core.utils.StringUtils.toSingular; +/** + * Options for the {@link OpenAPIGenerator}. + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder(toBuilder = true) @@ -44,10 +50,21 @@ public class OpenAPIGeneratorOptions { String listResponseNameFormat; String searchRequestNameFormat; + /** + * Load the options from an options file in YAML or Json. The options file may have missing + * (defined) values, in these cases the default values are loaded. See {@link #load()} + * @param optionsFile The path to the options file in YAML or Json. + * @return The options loaded from the YAML or Json file. + * @throws IOException if the options file can not be found or is incorrectly formatted. + */ public static OpenAPIGeneratorOptions load(Path optionsFile) throws IOException { return load(Files.newInputStream(optionsFile)); } + /** + * Load the default options + * @return The default options + */ public static OpenAPIGeneratorOptions load() { try { @@ -60,6 +77,25 @@ public static OpenAPIGeneratorOptions load() { } } + /** + * Load the options from an options input stream in YAML or Json. The options file may have missing + * (defined) values, in these cases the default values are loaded. See {@link #load()} + * @param inputStream The input stream in YAML or Json. + * @return The options loaded from input stream. + * @throws IOException if the input stream is not valid or the content is incorrectly formatted. + */ + public static OpenAPIGeneratorOptions load(InputStream inputStream) throws IOException { + + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + + return mapper.readValue(inputStream, OpenAPIGeneratorOptions.class); + } + + /** + * Creates a build class with the default options already loaded. This also for + * ease of overriding programmatically only a few options from their defaults. + * @return a build class with the default options already loaded. + */ public static OpenAPIGeneratorOptions.OpenAPIGeneratorOptionsBuilder defaultBuilder() { ObjectMapper objectMapper = new ObjectMapper(); try { @@ -72,140 +108,285 @@ public static OpenAPIGeneratorOptions.OpenAPIGeneratorOptionsBuilder defaultBuil } } - private static OpenAPIGeneratorOptions load(InputStream inputStream) throws IOException { - - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - - return mapper.readValue(inputStream, OpenAPIGeneratorOptions.class); - } - + /** + * Determines if the Generator should generate any Single Get Endpoints. Returns true if + * {@link SingleGetOptions#generating} is set to true or + * {@link SingleGetOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Single Get Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingSingleGet() { return singleGet != null && (singleGet.isGenerating() || singleGet.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any List Get Endpoints. Returns true if + * {@link ListGetOptions#generating} is set to true or + * {@link ListGetOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any List Get Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingListGet() { return listGet != null && (listGet.isGenerating() || listGet.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any Search Post or Get Endpoints. Returns true if + * {@link SearchOptions#generating} is set to true or + * {@link SearchOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Search Post or Get Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingSearch() { return search != null && (search.isGenerating() || search.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any Post Endpoints. Returns true if + * {@link PostOptions#generating} is set to true or + * {@link PostOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Post Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingPost() { return post != null && (post.isGenerating() || post.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any Put Endpoints. Returns true if + * {@link PutOptions#generating} is set to true or + * {@link PutOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Put Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingPut() { return put != null && (put.isGenerating() || put.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any Delete Endpoints. Returns true if + * {@link DeleteOptions#generating} is set to true or + * {@link DeleteOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Delete Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingDelete() { return delete != null && (delete.isGenerating() || delete.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate any Endpoints without an ID parameter. Returns true if + * {@link #isGeneratingListGet()} or {@link #isGeneratingPost()} is set to true + * @return true if the Generator should generate any Endpoints without an ID parameter, false otherwise + */ @JsonIgnore public boolean isGeneratingEndpoint() { return isGeneratingListGet() || isGeneratingPost(); } + /** + * Determines if the Generator should generate any Endpoints with an ID parameter. Returns true if + * {@link #isGeneratingSingleGet()} or {@link #isGeneratingPut()} or {@link #isGeneratingDelete()} is set to true + * @return true if the Generator should generate any Endpoints with an ID parameter, false otherwise + */ @JsonIgnore public boolean isGeneratingEndpointWithId() { return isGeneratingSingleGet() || isGeneratingPut() || isGeneratingDelete(); } + /** + * Determines if the Generator should generate any Search Post or Get Endpoints. Returns true if + * {@link SearchOptions#generating} is set to true or + * {@link SearchOptions#generatingFor} is set to true for any type + * @return true if the Generator should generate any Search Post or Get Endpoints, false otherwise + */ @JsonIgnore public boolean isGeneratingSearchEndpoint() { - return isGeneratingSingleGet() || isGeneratingPut() || isGeneratingDelete(); + return search != null && (search.isGenerating() || search.getGeneratingFor().values().stream().anyMatch(value -> value)); } + /** + * Determines if the Generator should generate the Single Get Endpoint for a specific Primary Model. Returns true if + * {@link SingleGetOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the Single Get Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingSingleGetEndpointFor(String name) { return singleGet != null && singleGet.generatingFor.getOrDefault(name, singleGet.isGenerating()) ; } + /** + * Determines if the Generator should generate the List Get Endpoint for a specific Primary Model. Returns true if + * {@link ListGetOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the List Get Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingListGetEndpointFor(String name) { return listGet != null && listGet.generatingFor.getOrDefault(name, listGet.isGenerating()) ; } + /** + * Determines if the Generator should generate the Post Endpoint for a specific Primary Model. Returns true if + * {@link PostOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the Post Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingPostEndpointFor(String name) { return post != null && post.generatingFor.getOrDefault(name, post.isGenerating()) ; } + /** + * Determines if the Generator should generate the Put Endpoint for a specific Primary Model. Returns true if + * {@link PutOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the Put Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingPutEndpointFor(String name) { return put != null && put.generatingFor.getOrDefault(name, put.isGenerating()) ; } + /** + * Determines if the Generator should generate the Delete Endpoint for a specific Primary Model. Returns true if + * {@link PostOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the Delete Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingDeleteEndpointFor(String name) { return delete != null && delete.generatingFor.getOrDefault(name, delete.isGenerating()) ; } + /** + * Determines if the Generator should generate the Search Post and Get Endpoint for a specific Primary Model. + * Returns true if + * {@link SearchOptions#generatingFor} is set to true for the specified type + * @param name the name of the Primary Model + * @return true if the Generator should generate the Search Post and Get Endpoint for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingSearchEndpointFor(String name) { return search != null && search.getGeneratingFor().getOrDefault(name, isGeneratingSearch()) ; } + /** + * Determines if the Generator should generate the Endpoints without an ID parameter for a specific Primary Model. Returns true if + * {@link #isGeneratingListGetEndpointFor(String)} or {@link #isGeneratingPostEndpointFor(String)} is set to true + * @param name the name of the Primary Model + * @return true if the Generator should generate the Endpoints without an ID parameter for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingEndpointFor(String name) { return isGeneratingListGetEndpointFor(name ) || isGeneratingPostEndpointFor(name) ; } + /** + * Determines if the Generator should generate the Endpoints with an ID parameter for a specific Primary Model. Returns true if + * {@link #isGeneratingSingleGetEndpointFor(String)} or {@link #isGeneratingPutEndpointFor(String)} or + * {@link #isGeneratingDeleteEndpointFor(String)}is set to true + * @param name the name of the Primary Model + * @return true if the Generator should generate the Endpoints with an ID parameter for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingEndpointNameWithIdFor(String name) { return isGeneratingSingleGetEndpointFor(name ) || isGeneratingPutEndpointFor(name) || isGeneratingDeleteEndpointFor(name) ; } + /** + * Determines if the Generator should generate a NewRequest schema, separate from the standard schema for a specific Primary Model. + * For example if set to true for the model 'Study' the generator will create the NewStudyRequest schema and the 'Study' schema, + * whereas if set false generator will create only create the 'Study' schema + * @param name the name of the Primary Model + * @return true if the Generator should generate a NewRequest schema, separate from the standard schema for a specific Primary Model, false otherwise + */ @JsonIgnore public boolean isGeneratingNewRequestFor(String name) { return creatingNewRequestFor.getOrDefault(name, creatingNewRequest) ; } + /** + * Gets the name for the NewRequest schema for a specific Primary Model + * @param name the name of the Primary Model + * @return the NewRequest schema name for a specific Primary Model + */ @JsonIgnore public String getNewRequestNameFor(String name) { return String.format(newRequestNameFormat, name) ; } + /** + * Determines if the Generator should generate the List Response for a specific Primary Model. + * @param name the name of the Primary Model + * @return true if the Generator generate the List Response for a specific Primary Model, false otherwise + */ public boolean isGeneratingListResponseFor(String name) { return listGet != null && listGet.isGeneratingFor(name) ; } + /** + * Gets the name for the Single Response for a specific Primary Model + * @param name the name of the Primary Model + * @return the Single Response name for a specific Primary Model + */ @JsonIgnore public String getSingleResponseNameFor(String name) { return String.format(singleResponseNameFormat, name) ; } + /** + * Gets the name for the List Response for a specific Primary Model + * @param name the name of the Primary Model + * @return the List Response name for a specific Primary Model + */ @JsonIgnore public String getListResponseNameFor(String name) { return String.format(listResponseNameFormat, name) ; } + /** + * Determines if the Generator should generate the Search Request schema for a specific Primary Model. + * @param name the name of the Primary Model + * @return true if the Generator generate the Search Request schema for a specific Primary Model, false otherwise + */ public boolean isGeneratingSearchRequestFor(String name) { return search != null && search.isGeneratingFor(name) ; } + /** + * Gets the name for the Search Request schema for a specific Primary Model + * @param name the name of the Primary Model + * @return the Search Request schema name for a specific Primary Model + */ @JsonIgnore public String getSearchRequestNameFor(String name) { return String.format(searchRequestNameFormat, name) ; } + /** + * Gets the Pluralise name for a specific Primary Model + * @param name the name of the Primary Model + * @return the Pluralise name for a specific Primary Model + */ @JsonIgnore public String getPluralFor(String name) { return toPlural(name) ; } + /** + * Gets the singular name for pluralised property name + * @param propertyName the pluralised property name + * @return the Pluralise name for a specific Primary Model + */ @JsonIgnore - public String getSingularForProperty(String name) { - return toSingular(name) ; + public String getSingularForProperty(String propertyName) { + return toSingular(propertyName) ; } + /** + * + */ public static class OpenAPIGeneratorOptionsBuilder {} } diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PostOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PostOptions.java index abca84f..375268c 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PostOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PostOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Post Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class PostOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Post Endpoint is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Post Endpoint is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PutOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PutOptions.java index ed0ed8e..cfd3e9d 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PutOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/PutOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Put Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class PutOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Put Endpoint is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Put Endpoint is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SearchOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SearchOptions.java index 14a93e6..25b86e0 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SearchOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SearchOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Search Post and Get Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -22,6 +25,11 @@ public class SearchOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Search Post and Get Endpoints are generated for a specific primary model + * @param name the name of the primary model + * @return true if the Search Post and Get Endpoints are generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SingleGetOptions.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SingleGetOptions.java index 833861e..694f328 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SingleGetOptions.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/options/SingleGetOptions.java @@ -7,6 +7,9 @@ import java.util.HashMap; import java.util.Map; +/** + * Provides options for the generation of Single Get Endpoints + */ @Getter @Setter(AccessLevel.PRIVATE) @Builder @@ -21,6 +24,11 @@ public class SingleGetOptions { @Builder.Default Map generatingFor = new HashMap<>(); + /** + * Determines if the Single Get Endpoint is generated for a specific primary model + * @param name the name of the primary model + * @return true if the Single Get Endpoint is generated for a specific primary model, false otherwise + */ @JsonIgnore public boolean isGeneratingFor(String name) { return generatingFor.getOrDefault(name, generating) ; diff --git a/java/core/src/main/java/org/brapi/schematools/core/response/Response.java b/java/core/src/main/java/org/brapi/schematools/core/response/Response.java index d64042a..e55df2c 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/response/Response.java +++ b/java/core/src/main/java/org/brapi/schematools/core/response/Response.java @@ -9,6 +9,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +/** + * A generic Response class for functional programming. + * A successful Response is one that has no errors, whereas a failed Response has errors + * + * @param The type of result + */ @Slf4j public class Response { private T result; @@ -35,10 +41,21 @@ private Response(Response response) { this.result = response.result; } + /** + * Creates a successful response for the provided result + * @param result the result + * @return a successful response for the provided result + * @param The type of the result + */ public static Response success(T result) { return new Response<>(result); } + /** + * Creates an empty response + * @return a empty response + * @param The type of the result + */ public static Response empty() { return new Response<>(); } @@ -58,24 +75,58 @@ private static Response fail(ErrorType type, Error error) { return response; } + /** + * Creates a failed response + * @param type The type of error + * @param code The error code + * @param message The error message + * @return an empty response with the added error + * @param The type of the result + */ public static Response fail(ErrorType type, String code, String message) { return fail(type, Error.of(code, message, type)); } + /** + * Creates a failed response + * @param type The type of error + * @param message The error message + * @return an empty response with the added error + * @param The type of the result + */ public static Response fail(ErrorType type, String message) { return fail(type, "", message); } + /** + * Creates a failed response, and executes a logging call back + * @param type The type of error + * @param message The error message + * @param errorLogging the error logging functional interface + * @return an empty response with the added error + * @param The type of the result + */ public static Response failWithLogging(ErrorType type, String message, ErrorLogging errorLogging) { errorLogging.executeLogging(); return fail(type, "", message); } + /** + * Functional Interface to support error logging. + */ @FunctionalInterface public interface ErrorLogging { + /** + * Execute the error logging + */ void executeLogging(); } + /** + * Merge the errors from the provided response into this response + * @param response the provided response which is the source of the errors + * @return this response + */ public Response mergeErrors(Response response) { this.getErrors(ErrorType.VALIDATION).addAll(response.getErrors(ErrorType.VALIDATION)); this.getErrors(ErrorType.PERMISSION).addAll(response.getErrors(ErrorType.PERMISSION)); @@ -83,6 +134,12 @@ public Response mergeErrors(Response response) { return this; } + /** + * Merge the errors from the provided response supplier into this response + * @param supplier the supplier which providers the response that is the source of the errors + * @return this response + * @param the result type of the output response for the provided supplier + */ public Response mergeErrors(Supplier> supplier) { Response response = supplier.get(); this.getErrors(ErrorType.VALIDATION).addAll(response.getErrors(ErrorType.VALIDATION)); @@ -91,6 +148,13 @@ public Response mergeErrors(Supplier> supplier) { return this; } + /** + * Map the errors response of the provided function executed on this response, removing any + * existing errors on this response + * @param function the function which providers the response that is the source of the errors + * @return this response + * @param the result type of the output response for the provided function + */ public Response mapErrors(Function, Response> function) { Response response = function.apply(this); this.getErrors(ErrorType.VALIDATION).clear(); @@ -102,6 +166,12 @@ public Response mapErrors(Function, Response> function) { return this; } + /** + * If this response has no errors it maps result of the provided function executed on the result on this response + * @param function the function which takes the result of this and returns a new response + * @return this response + * @param the result type of the output response for the provided function + */ public Response mapResultErrors(Function> function) { if (this.hasNoErrors()) { Response response = function.apply(this.getResult()); @@ -112,47 +182,101 @@ public Response mapResultErrors(Function> function) { return this; } + /** + * Get the result of this response if there are no errors. If there are errors a {@link RuntimeException} is thrown + * @return the result of this response if there are no errors + */ public T getResult() { if (this.hasNoErrors()) return this.result; else throw new RuntimeException(String.format("Trying to access the result while an error has occurred, [%s]", this.getMessagesCombined(";"))); } + /** + * Get the result of this response if there are no errors in this response, otherwise returns the provided result + * @param result the result that is return if there are errors in this response + * @return the result of this response if there are no errors in this response or the provided result + */ public T orElseResult(T result) { return this.hasErrors() ? result : this.getResult(); } + /** + * Get the result of this response if there are no errors in this response, otherwise returns supplier + * is used to provide result + * @param supplier the supplier that provides the result if there are errors in this response + * @return the result of this response if there are no errors in this response or the result from the supplier + */ public T orElseGetResult(Supplier supplier) { return this.hasErrors() ? supplier.get() : this.getResult(); } + /** + * Get the result of this response if there are no errors in this response, otherwise throws the + * provided exception + * @param ex the exception to be thrown if there are errors in this response + * @return the result of this response if there are no errors in this response + * @throws Exception the provided exception if there are errors + */ public T getResultOrThrow(Exception ex) throws Exception { if (this.hasErrors()) throw ex; return this.getResult(); } + /** + * Get the result of this response if there are no errors in this response, otherwise obtains + * an exception from the supplier to be thrown. + * @param supplier the supplier exception to be used if there are errors in this response + * @return the result of this response if there are no errors in this response + */ public T getResultOrThrow(Supplier supplier) { if (this.hasErrors()) throw supplier.get(); return this.getResult(); } + /** + * Get the result of this response if there are no errors in this response, otherwise obtains + * an exception from the function to be thrown. + * @param function the function use to create the exception to be thrown if there are errors in this response + * @return the result of this response if there are no errors in this response + */ public T getResultOrThrow(Function, ? extends RuntimeException> function) { if (this.hasErrors()) throw function.apply(this); return this.getResult(); } + /** + * Get the result of this response if there are no errors in this response, or throws an + * {@link ResponseFailedException} + * @return the result of this response if there are no errors in this response + */ public T getResultOrThrow() { return getResultOrThrow(() -> new ResponseFailedException(this)); } + /** + * Determines if this response has any errors. + * @return true if this response has any errors, false otherwise + */ public boolean hasErrors() { return !this.getValidationErrors().isEmpty() || !this.getPermissionErrors().isEmpty() || !this.getOtherErrors().isEmpty(); } + /** + * Determines if this response has no errors. + * @return true if this response has no errors, false otherwise + */ public boolean hasNoErrors() { return this.getValidationErrors().isEmpty() && this.getPermissionErrors().isEmpty() && this.getOtherErrors().isEmpty(); } + /** + * Merges any errors from this response into provided response, + * the result from this response is lost. + * @param response the response uses as a source of errors. + * @return the provided response + * @param the result type of the provided response + */ public Response merge(Response response) { response.getErrors(ErrorType.VALIDATION).addAll(this.getErrors(ErrorType.VALIDATION)); response.getErrors(ErrorType.PERMISSION).addAll(this.getErrors(ErrorType.PERMISSION)); @@ -160,6 +284,13 @@ public Response merge(Response response) { return response; } + /** + * Merges any errors from this response into response obtained from the provider supplier, + * the result from this response is lost. + * @param responseSupplier the supplier used to provide the response + * @return the provided response from the supplier + * @param the result type of the provided response + */ public Response merge(Supplier> responseSupplier) { final var response = responseSupplier.get(); response.getErrors(ErrorType.VALIDATION).addAll(this.getErrors(ErrorType.VALIDATION)); @@ -168,42 +299,112 @@ public Response merge(Supplier> responseSupplier) { return response; } + /** + * If the condition is true merges any errors from this response into response obtained + * from the provided supplier, the result from this response is lost. + * @param condition set to true to perform the merge, false not to perform the merge + * @param supplier a supplier of the provided response + * @return the provided response from the supplier + * @param the result type of the provided response + */ public Response mergeOnCondition(boolean condition, Supplier> supplier) { return condition ? this.merge(supplier.get()) : new Response().mergeErrors(this); } + /** + * If the condition is true and there are no errors from this response + * merge the response obtained from the provided function, otherwise create a new response and merge in the errors + * from this response. In either case the result from this response is lost. + * @param condition set to true to perform the mapping, false not to perform the mapping + * @param function a function that takes this response and provides a new response + * @return the provided response from the function if the condition is true and there are no errors + * from this response or a new response + * @param the result type of the provided response + */ public Response mapOnCondition(boolean condition, Function, Response> function) { return condition && this.hasNoErrors() ? this.merge(function.apply(this)) : new Response().mergeErrors(this); } + /** + * If the condition is true and there are no errors from this response + * merge any errors from this response into response obtained from the provided supplier, + * otherwise create a new response and merge in the errors + * from this response. In either case the result from this response is lost. + * @param condition set to true to perform the merge, false not to perform the merge + * @param supplier a supplier that provides a new response + * @return the provided response from the supplier + * @param the result type of the provided response + */ public Response mapOnCondition(boolean condition, Supplier> supplier) { return condition && this.hasNoErrors() ? this.merge(supplier.get()) : new Response().mergeErrors(this); } + /** + * If the condition is true merges any errors from this response into response obtained from the + * provided function, otherwise create a new response and merges in the errors + * from this response. In either case the result from this response is lost. + * @param condition set to true to perform the merge, false not to perform the merge + * @param function a function that takes this response and provides a new response + * @return the provided response from the function + * @param the result type of the provided response + */ public Response mapResponseOnCondition(boolean condition, Function> function) { return condition && this.hasNoErrors() ? this.merge(function.apply(this.getResult())) : new Response().mergeErrors(this); } + /** + * Merges the response from the supplier if this response has no errors, otherwise create a new response and merges in the errors + * from this response. In either case the result from this response is lost. + * @param supplier a supplier that provides a new response + * @return the provided response from the supplier + * @param the result type of the provided response + */ public Response map(Supplier> supplier) { return mergeOnCondition(this.hasNoErrors(), supplier); } + /** + * Merges the response from the function if this response has no errors, otherwise create a new response and merges in the errors + * from this response. In either case the result from this response is lost. + * @param function a function that takes this response and provides a new response + * @return the provided response from the function + * @param the result type of the provided response + */ public Response map(Function, Response> function) { return this.hasNoErrors() ? function.apply(this) : new Response().mergeErrors(this); } + /** + * Returns this response if it has no errors, otherwise returns the provided response from the supplier + * @param supplier a supplier that provides a new response + * @return this response if it has no errors, otherwise returns the provided response from the supplier + */ public Response or(Supplier> supplier) { return this.hasErrors() ? supplier.get() : this; } + /** + * Returns this response if it has no errors, otherwise returns the provided response + * @param response a new response + * @return this response if it has no errors, otherwise returns the provided response + */ public Response orElse(Response response) { return this.or(() -> response); } + /** + * If this response has no errors returns a new response that takes the + * result of provided function that takes the result of this resource as an input, + * otherwise create a new response and merges in the errors + * from this response. + * @param function a function that takes the result of this response as an input + * @return a new response with result of the function, or with any merged errors + * @param the result type of the new response + */ public Response mapResult(Function function) { if (this.hasNoErrors()) { return new Response<>(function.apply(this.getResult())); @@ -212,6 +413,13 @@ public Response mapResult(Function function) { } } + /** + * If this response has no errors creates a new Response with the provided result, otherwise + * a new Response with the errors from this resource. + * @param result the new result + * @return the new Response + * @param the result type of the new response + */ public Response withResult(RESULT result) { if (this.hasNoErrors()) { return new Response<>(result); @@ -220,14 +428,28 @@ public Response withResult(RESULT result) { } } - public Response withResult(Supplier result) { + /** + * If this response has no errors creates a new Response with the result from the supplier, otherwise + * a new Response with the errors from this resource. + * @param supplier a supplier for this new result + * @return the new Response + * @param the result type of the new response + */ + public Response withResult(Supplier supplier) { if (this.hasNoErrors()) { - return new Response<>(result.get()); + return new Response<>(supplier.get()); } else { - return new Response().mergeErrors(this); + return new Response().mergeErrors(this); } } + /** + * If the condition is true and this response has no errors creates a new Response + * with the result from the function, otherwise a new Response with the errors from this resource. + * @param condition true map the result, false do not map the result + * @param function that takes the result from this response and returns a new result of the same type + * @return a new Response or returns this + */ public Response conditionalMapResult(boolean condition, UnaryOperator function) { if (this.hasNoErrors()) { return condition ? new Response<>(function.apply(this.getResult())) : this; @@ -236,6 +458,13 @@ public Response conditionalMapResult(boolean condition, UnaryOperator func } } + /** + * If the predicate returns true and this response has no errors creates a new Response + * with the result from the function, otherwise a new Response with the errors from this resource. + * @param predicate if the predicate returns true map the result, false do not map the result + * @param supplier that provides a new result of the same type + * @return a new Response or returns this + */ public Response conditionalMapResultToResponse(Predicate predicate, Supplier> supplier) { if (this.hasNoErrors()) { return predicate.test(this.getResult()) ? supplier.get() : this; @@ -244,6 +473,13 @@ public Response conditionalMapResultToResponse(Predicate predicate, Suppli } } + /** + * If the predicate returns true and this response has no errors creates a new Response + * with the result from the function, otherwise a new Response with the errors from this resource. + * @param predicate if the predicate returns true map the result, false do not map the result + * @param function that takes the result from this response and returns a new result of the same type + * @return a new Response or returns this + */ public Response conditionalMapResultToResponse(Predicate predicate, Function> function) { if (this.hasNoErrors()) { return predicate.test(this.getResult()) ? function.apply(this.getResult()) : this; @@ -252,6 +488,13 @@ public Response conditionalMapResultToResponse(Predicate predicate, Functi } } + /** + * If the condition is true and this response has no errors use the supplier to get + * the new response + * @param condition true map the result, false do not map the result + * @param supplier that providers a new Response + * @return a new Response or returns this + */ public Response conditionalMapResultToResponse(boolean condition, Supplier> supplier) { if (this.hasNoErrors()) { return condition ? supplier.get() : this; @@ -260,6 +503,13 @@ public Response conditionalMapResultToResponse(boolean condition, Suppliertrue and this response has no errors use the function to get + * the new response + * @param condition true map the result, false do not map the result + * @param function a function that providers a new Response taking the result of this response as input + * @return a new Response or returns this + */ public Response conditionalMapResultToResponse(boolean condition, Function> function) { if (this.hasNoErrors()) { return condition ? function.apply(this.getResult()) : this; @@ -268,6 +518,12 @@ public Response conditionalMapResultToResponse(boolean condition, Function the result type of the new response + */ public Response mapResultToResponse(Function> function) { if (this.hasNoErrors()) { return function.apply(this.getResult()); @@ -276,34 +532,56 @@ public Response mapResultToResponse(Function> function) { } } + /** + * Call the supplier and return this + * @param supplier the supplier to be called. + * @return this response + */ public Response justDo(Supplier supplier) { supplier.get(); return this; } + /** + * If the condition is true call the supplier, otherwise don't call the supplier + * @param condition true call the supplier, false don't call the supplier + * @param supplier the supplier to be called if the condition is true + * @return this response + */ public Response justDoOnCondition(boolean condition, Supplier supplier) { if (condition) supplier.get(); return this; } + /** + * If this response has no errors pass this response to the provider consumer + * @param consumer a consumer for this response + * @return this response + */ public Response onSuccessDo(Consumer> consumer) { - if (this.hasErrors()) { - return this; - } else { + if (!this.hasErrors()) { consumer.accept(this); - return this; } + return this; } + /** + * If this response has no errors call the supplier and return this + * @param supplier the supplier to be called if there are no errors + * @return this response + */ public Response onSuccessDo(Supplier supplier) { - if (this.hasErrors()) { - return this; - } else { + if (!this.hasErrors()) { supplier.get(); - return this; } + return this; } + /** + * If this response has no errors run the action and return this + * @param action the action to be run if there are no errors + * @return this response + */ public Response onSuccessDo(Runnable action) { if (this.hasErrors()) { return this; @@ -313,6 +591,11 @@ public Response onSuccessDo(Runnable action) { } } + /** + * If this response has no errors pass the result of this response to the provider consumer + * @param consumer a consumer for the result of this response + * @return this response + */ public Response onSuccessDoWithResult(Consumer consumer) { if (this.hasErrors()) { return this; @@ -322,24 +605,38 @@ public Response onSuccessDoWithResult(Consumer consumer) { } } - public Response onSuccessDoOnCondition(Predicate condition, Supplier supplier) { - if (this.hasErrors()) { - return this; - } else { - if (condition.test(this.getResult())) supplier.get(); - return this; + /** + * If the predicate returns true and this response has no errors call the supplier and return this + * @param predicate if the predicate returns true call the supplier, false do not call the supplier + * @param supplier the supplier to be called if the predicate returns true and there are no errors + * @return this response + */ + public Response onSuccessDoOnCondition(Predicate predicate, Supplier supplier) { + if (!this.hasErrors()) { + if (predicate.test(this.getResult())) supplier.get(); } + return this; } - public Response onSuccessDoOnCondition(final Predicate condition, final Runnable runnable) { - if (this.hasErrors()) { - return this; - } else { - if (condition.test(this.getResult())) runnable.run(); - return this; + /** + * If the predicate returns true and this response has no errors call run the action and return this + * @param predicate if the predicate returns true run the action, false do not run the action + * @param action the action to be run if the predicate returns true and there are no errors + * @return this response + */ + public Response onSuccessDoOnCondition(final Predicate predicate, final Runnable action) { + if (!this.hasErrors()) { + if (predicate.test(this.getResult())) action.run(); } + return this; } + /** + * If the condition is true and this response has no errors call run the action and return this + * @param condition if is true run the action, false do not run the action + * @param action the action to be run if the predicate returns true and there are no errors + * @return this response + */ public Response onSuccessDoOnCondition(final boolean condition, final Runnable action) { if (!this.hasErrors() && condition) { action.run(); @@ -347,39 +644,75 @@ public Response onSuccessDoOnCondition(final boolean condition, final Runnabl return this; } - public Response onFailDo(final Runnable callBack) { + /** + * If this response has errors run the action and return this + * @param action the action to be run if there are errors + * @return this response + */ + public Response onFailDo(final Runnable action) { if (this.hasErrors()) { - callBack.run(); + action.run(); } return this; } + /** + * If this response has no errors pass this response to the provider consumer + * @param consumer a consumer for this response + * @return this response + */ public Response onFailDoWithResponse(Consumer> consumer) { if (this.hasErrors()) { consumer.accept(this); - return this; - } else { - return this; } + return this; } + /** + * Determines if response has no errors and the result is not null + * @return If response has no errors and the result is not null + */ public boolean isPresent() { return !this.hasErrors() && result != null; } + /** + * Determines if response has no errors and the result is null + * @return If response has no errors and the result is null + */ public boolean isEmpty() { return !this.hasErrors() && result == null; } + /** + * If response has no errors and the result is not null return the result, otherwise + * return the result from the supplier + * @param supplier the supplier to be used if response has no errors and the result is not null + * @return the result from this response or from the supplier + */ public T getResultIfPresentOrElseResult(Supplier supplier) { return this.isPresent() ? this.getResult() : supplier.get(); } + /** + * If response has no errors and the result is not null return the result, otherwise + * return the provider result from the supplier + * @param result the result to returned if response has no errors and the result for this response is not null + * @return the result from this response or from the supplier + */ public T getResultIfPresentOrElseResult(T result) { return this.isPresent() ? this.getResult() : result; } + /** + * If response has no errors and the result is not null apply the function to the result, otherwise use the + * to get the new resource + * @param function a function that takes the result of this response to create a new response + * @param supplier a supplier that provides a new response + * @return a new response from the function or supplier + * @param the result type of the new response + */ public Response ifPresentMapResultToResponseOr(Function> function, Supplier> supplier) { if (this.isPresent()) { return function.apply(this.getResult()); @@ -388,6 +721,13 @@ public Response ifPresentMapResultToResponseOr(Function> f } } + /** + * Adds an error to the response. + * + * @param type The type of error + * @param error The error + * @return this response + */ public Response addError(ErrorType type, Error error) { switch (type) { case VALIDATION: @@ -403,56 +743,114 @@ public Response addError(ErrorType type, Error error) { return new Response<>(this); } + /** + * Adds an error to the response. + * + * @param type The type of error + * @param code The error code + * @param message The error message + * @return this response + */ public Response addError(ErrorType type, String code, String message) { return this.addError(type, Error.of(code, message, type)); } + /** + * Gets the errors by error type + * @param errorType the type of error required + * @return the errors for the provided type + */ private Set getErrors(ErrorType errorType) { return this.errors.get(errorType); } + /** + * Get the validation errors in this response + * @return the validation errors in this response + */ public Collection getValidationErrors() { return Collections.unmodifiableSet(getErrors(ErrorType.VALIDATION)); } + /** + * Get the permission errors in this response + * @return the permission errors in this response + */ public Collection getPermissionErrors() { return Collections.unmodifiableSet(getErrors(ErrorType.PERMISSION)); } + /** + * Get the other errors in this response + * @return the other errors in this response + */ public Collection getOtherErrors() { return Collections.unmodifiableSet(getErrors(ErrorType.OTHER)); } + /** + * Get the all errors in this response, regardless of type + * @return the all errors in this response, regardless of type + */ public Collection getAllErrors() { return Stream.concat(Stream.concat(getErrors(ErrorType.VALIDATION).stream(), getErrors(ErrorType.PERMISSION).stream()), getErrors(ErrorType.OTHER).stream()).collect(Collectors.toList()); } - + /** + * Gets a list of all the error message for this response + * @return a list of all the error message for this response + */ public List getMessages() { return Stream.concat(Stream.concat(getErrors(ErrorType.VALIDATION).stream(), getErrors(ErrorType.PERMISSION).stream()), getErrors(ErrorType.OTHER).stream()) .map(Error::getMessage) .collect(Collectors.toList()); } + /** + * Gets a combined error message for all the error messages for this response, separated with the provided delimiter + * @param delimiter the delimiter to separate the individual error messages in the combined error message + * @return a combined error message for all the error messages for this response, separated with the provided delimiter + */ public String getMessagesCombined(String delimiter) { return String.join(delimiter, getMessages()); } + /** + * Combines all the results from a stream of Responses of type {@link T} into a single Response that has a result of type {@link List}, + * merging any errors from the individual responses into the returned response. + * @return a single Response that has a result of type {@link List} + * @param the type of the result + */ public static Collector, Response>, Response>> toList() { return Collector.of(() -> new Response<>(new ArrayList<>()), getResultToResultListAccumulator(), getListCombiner(), Collector.Characteristics.IDENTITY_FINISH); } + /** + * Combines all the results a stream of Responses of type{@link T} into a single Response that has a result of type {@link Set}, + * merging any errors from the individual responses into the returned response. + * @return a single Response that has a result of type {@link Set} + * @param the type of the result + */ public static Collector, Response>, Response>> toSet() { return Collector.of(() -> new Response<>(new HashSet<>()), getResultToResultSetAccumulator(), getSetCombiner(), Collector.Characteristics.UNORDERED); } + /** + * Combines all the results a stream of Responses of type {@link List}into a single Response that has a result of type {@link List}, + * merging any errors from the individual responses into the returned response. + * @return a single Response that has a result of {@link List} + * @param the type of the result + */ public static Collector>, Response>, Response>> mergeLists() { return Collector.of(() -> new Response<>(new ArrayList<>()), getResultListAccumulator(), getListCombiner(), Collector.Characteristics.IDENTITY_FINISH); } + /** + * Wrapper around an error in the response. + */ @Value(staticConstructor = "of") public static class Error { String code; @@ -460,9 +858,21 @@ public static class Error { ErrorType type; } + /** + * Type of error + */ public enum ErrorType { + /** + * Validation errors + */ VALIDATION, + /** + * Permission errors + */ PERMISSION, + /** + * Any other types of error + */ OTHER } diff --git a/java/core/src/main/java/org/brapi/schematools/core/response/ResponseFailedException.java b/java/core/src/main/java/org/brapi/schematools/core/response/ResponseFailedException.java index 8dd3b72..c449f44 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/response/ResponseFailedException.java +++ b/java/core/src/main/java/org/brapi/schematools/core/response/ResponseFailedException.java @@ -2,10 +2,16 @@ import lombok.Getter; +/** + * Exception thrown when Response error is handled. + */ @Getter public class ResponseFailedException extends IllegalStateException { private final transient Response failedResponse; + /** Constructs a new exception with failed Response + * @param failedResponse the failedResponse + */ public ResponseFailedException(Response failedResponse) { super(); this.failedResponse = failedResponse; diff --git a/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java b/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java index 2f52c43..36fd9f8 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java +++ b/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java @@ -8,6 +8,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Utility class for working with Strings + */ public class StringUtils { private static final Set unpluralisables = ImmutableSet.of( "equipment", "information", "rice", "money", "species", "series", From 1a875c7c837a1849833c9c8cb0527f8bb9ca4aca Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Tue, 11 Jun 2024 19:22:52 +1200 Subject: [PATCH 7/9] Changed version to SNAPSHOT, and updated tests etc --- ...brapi.schema-tools.java-conventions.gradle | 2 +- java/core/build.gradle | 7 ++++- .../core/brapischema/BrAPISchemaReader.java | 26 +++++++++---------- .../BrAPISchemaReaderException.java | 10 +++++++ .../core/graphql/GraphQLGenerator.java | 2 +- .../schematools/core/model/BrAPIMetadata.java | 1 + .../core/model/BrAPIObjectType.java | 1 - .../brapischema/BrAPISchemaReaderTest.java | 26 ++++++++++++++++++- .../core/graphql/GraphQLGeneratorTest.java | 1 + .../core/openapi/OpenAPIGeneratorTest.java | 2 ++ .../BrAPI-Schema/Requests/ListRequest.json | 3 +++ .../Requests/LocationRequest.json | 5 +++- 12 files changed, 66 insertions(+), 20 deletions(-) diff --git a/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle b/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle index 2553f0b..d3e0042 100644 --- a/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle +++ b/java/buildSrc/src/main/groovy/brapi.schema-tools.java-conventions.gradle @@ -3,7 +3,7 @@ plugins { } group = 'org.brapi' -version = '0.1.0' +version = '0.2.0-SNAPSHOT' sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 diff --git a/java/core/build.gradle b/java/core/build.gradle index 1677dbf..f9febd0 100644 --- a/java/core/build.gradle +++ b/java/core/build.gradle @@ -24,7 +24,12 @@ publishing { repositories { maven { name = "OSSRH" - url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + if(project.version.endsWith('-SNAPSHOT')) { + url = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + } else { + url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + } + credentials { username = System.getenv("MAVEN_USERNAME") password = System.getenv("MAVEN_PASSWORD") diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java index 82ceba3..5075c43 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java @@ -104,9 +104,10 @@ public BrAPIClass readSchema(Path schemaPath, String module) throws BrAPISchemaR public 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)). - getResultOrThrow(response -> new RuntimeException(response.getMessagesCombined(","))); + getResultOrThrow(response -> new RuntimeException( + String.format("Can not read schema at '%s' in module '%s' from '%s', due to '%s'", path, module, schema, response.getMessagesCombined(",")))); } catch (RuntimeException | JsonProcessingException e) { - throw new BrAPISchemaReaderException(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); } } @@ -152,9 +153,9 @@ private Stream> createBrAPISchemas(Path path) { } private String findModule(Path path) { - String module = path.getParent().getFileName().toString(); + String module = path != null ? path.getParent().getFileName().toString() : null; - return COMMON_MODULES.contains(module) ? null : module; + return module != null && COMMON_MODULES.contains(module) ? null : module; } private Stream> createBrAPISchemas(Path path, String module) { @@ -211,7 +212,7 @@ private Response createType(Path path, JsonNode jsonNode, String fall if (isEnum) { return fail(Response.ErrorType.VALIDATION, String.format("Object Type '%s' can not be an enum!", fallbackName)); } else { - return createObjectType(path, jsonNode, findNameFromTitle(jsonNode).getResultIfPresentOrElseResult(fallbackName), module, isRequestPath(path)); + return createObjectType(path, jsonNode, findNameFromTitle(jsonNode).getResultIfPresentOrElseResult(fallbackName), module); } } @@ -261,10 +262,6 @@ private Response createType(Path path, JsonNode jsonNode, String fall } - private boolean isRequestPath(Path path) { - return path.getParent().getFileName().endsWith("Requests") ; - } - private Response findNameFromTitle(JsonNode jsonNode) { return findString(jsonNode, "title", false).mapResult(name -> name != null ? name.replace(" ", "") : null); } @@ -307,11 +304,10 @@ private Response createArrayType(Path path, JsonNode jsonNode, String map(() -> success(builder.build())); } - private Response createObjectType(Path path, JsonNode jsonNode, String name, String module, boolean request) { + private Response createObjectType(Path path, JsonNode jsonNode, String name, String module) { BrAPIObjectType.BrAPIObjectTypeBuilder builder = BrAPIObjectType.builder(). name(name). - request(request). module(module); findString(jsonNode, "description", false). @@ -357,8 +353,10 @@ private Response createProperty(Path path, JsonNode jsonNod private Response parseMetadata(JsonNode metadata) { BrAPIMetadata.BrAPIMetadataBuilder builder = BrAPIMetadata.builder(); - return findBoolean(metadata, "primaryModel", false). + return findBoolean(metadata, "primaryModel", false, false). onSuccessDoWithResult(builder::primaryModel). + merge(findBoolean(metadata, "request", false, false)). + onSuccessDoWithResult(builder::request). map(() -> success(builder.build())); } @@ -458,7 +456,7 @@ private Response findString(JsonNode parentNode, String fieldName, boole }); } - private Response findBoolean(JsonNode parentNode, String fieldName, boolean required) { + private Response findBoolean(JsonNode parentNode, String fieldName, boolean required, boolean defaultValue) { return findChildNode(parentNode, fieldName, required).mapResultToResponse(jsonNode -> { if (jsonNode instanceof BooleanNode booleanNode) { return success(booleanNode.asBoolean()); @@ -466,7 +464,7 @@ private Response findBoolean(JsonNode parentNode, String fieldName, boo return required ? fail(Response.ErrorType.VALIDATION, String.format("Child node type '%s' was not BooleanNode with field name '%s' for parent node '%s'", jsonNode.getClass().getName(), parentNode, fieldName)) : - Response.empty(); + Response.success(defaultValue); }); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java index 7ade7e3..23e2557 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderException.java @@ -14,4 +14,14 @@ public class BrAPISchemaReaderException extends Exception { public BrAPISchemaReaderException(Exception cause) { super(cause) ; } + + /** Constructs a new exception with the specified detail message and cause. + * Note that the detail message associated with cause is not automatically incorporated in this exception's detail message. + * @param message – the detail message (which is saved for later retrieval by the getMessage() method). + * @param cause – the cause (which is saved for later retrieval by the getCause() method). + * (A null value is permitted, and indicates that the cause is nonexistent or unknown.) + */ + public BrAPISchemaReaderException(String message, Exception cause) { + super(message, cause) ; + } } diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java index dbf588f..8bcb75c 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java @@ -137,7 +137,7 @@ public Response generate() { } private boolean isInputType(BrAPIClass type) { - return type instanceof BrAPIObjectType && ((BrAPIObjectType) type).isRequest() ; + return type instanceof BrAPIObjectType && type.getMetadata() != null && type.getMetadata().isRequest() ; } private boolean isPrimaryModel(BrAPIClass type) { diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java index 65c43ae..210ff6a 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIMetadata.java @@ -10,4 +10,5 @@ @Value public class BrAPIMetadata { boolean primaryModel ; + boolean request ; } diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java index 9c16b80..13bcca2 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectType.java @@ -15,6 +15,5 @@ public class BrAPIObjectType implements BrAPIClass { String description; String module; BrAPIMetadata metadata; - boolean request; List properties; } \ No newline at end of file diff --git a/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java b/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java index 411db44..c4d97c8 100644 --- a/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java +++ b/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java @@ -70,9 +70,11 @@ void readDirectories() { assertNotNull(listRequest); assertEquals("ListRequest", listRequest.getName()); assertNull(listRequest.getModule()); - assertNull(listRequest.getMetadata()); + assertNotNull(listRequest.getMetadata()); + assertTrue(listRequest.getMetadata().isRequest()); } catch (Exception e) { + e.printStackTrace(); fail(e.getMessage()); } } @@ -100,7 +102,17 @@ void readSchemaPath() { assertEquals("Trial", trialSchema.getName()); assertEquals("BrAPI-Core", trialSchema.getModule()); assertNull(listTypeSchema.getMetadata()); + + BrAPIClass listRequest = + new BrAPISchemaReader().readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/Requests/ListRequest.json").toURI()), null); + + assertNotNull(listRequest); + assertEquals("ListRequest", listRequest.getName()); + assertNull(listRequest.getModule()); + assertNotNull(listRequest.getMetadata()); + assertTrue(listRequest.getMetadata().isRequest()); } catch (Exception e) { + e.printStackTrace(); fail(e.getMessage()); } } @@ -132,7 +144,19 @@ void readSchemaString() { assertEquals("Trial", trialSchema.getName()); assertEquals("BrAPI-Core", trialSchema.getModule()); assertNull(listTypeSchema.getMetadata()); + + path = Paths.get(Objects.requireNonNull(this.getClass().getResource("/BrAPI-Schema/Requests/ListRequest.json")).toURI()); + + BrAPIClass listRequest = + new BrAPISchemaReader().readSchema(null, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), null); + + assertNotNull(listRequest); + assertEquals("ListRequest", listRequest.getName()); + assertNull(listRequest.getModule()); + assertNotNull(listRequest.getMetadata()); + assertTrue(listRequest.getMetadata().isRequest()); } catch (Exception e) { + e.printStackTrace(); fail(e.getMessage()); } } diff --git a/java/core/src/test/java/org/brapi/schematools/core/graphql/GraphQLGeneratorTest.java b/java/core/src/test/java/org/brapi/schematools/core/graphql/GraphQLGeneratorTest.java index 55a97be..acfd075 100644 --- a/java/core/src/test/java/org/brapi/schematools/core/graphql/GraphQLGeneratorTest.java +++ b/java/core/src/test/java/org/brapi/schematools/core/graphql/GraphQLGeneratorTest.java @@ -18,6 +18,7 @@ void generate() { try { schema = new GraphQLGenerator().generate(Path.of(ClassLoader.getSystemResource("BrAPI-Schema").toURI())); } catch (URISyntaxException e) { + e.printStackTrace(); throw new RuntimeException(e); } assertNotNull(schema); diff --git a/java/core/src/test/java/org/brapi/schematools/core/openapi/OpenAPIGeneratorTest.java b/java/core/src/test/java/org/brapi/schematools/core/openapi/OpenAPIGeneratorTest.java index 18be82a..590f62b 100644 --- a/java/core/src/test/java/org/brapi/schematools/core/openapi/OpenAPIGeneratorTest.java +++ b/java/core/src/test/java/org/brapi/schematools/core/openapi/OpenAPIGeneratorTest.java @@ -26,6 +26,7 @@ void generate() { specifications = new OpenAPIGenerator(OpenAPIGeneratorOptions.builder().separatingByModule(false).build()). generate(Path.of(ClassLoader.getSystemResource("BrAPI-Schema").toURI()), Path.of(ClassLoader.getSystemResource("OpenAPI-Components").toURI())); } catch (URISyntaxException e) { + e.printStackTrace(); throw new RuntimeException(e); } assertNotNull(specifications); @@ -43,6 +44,7 @@ void generateByModule() { specifications = new OpenAPIGenerator(OpenAPIGeneratorOptions.builder().separatingByModule(true).build()). generate(Path.of(ClassLoader.getSystemResource("BrAPI-Schema").toURI()), Path.of(ClassLoader.getSystemResource("OpenAPI-Components").toURI())); } catch (URISyntaxException e) { + e.printStackTrace(); throw new RuntimeException(e); } assertNotNull(specifications); diff --git a/java/core/src/test/resources/BrAPI-Schema/Requests/ListRequest.json b/java/core/src/test/resources/BrAPI-Schema/Requests/ListRequest.json index a90da6b..0256400 100644 --- a/java/core/src/test/resources/BrAPI-Schema/Requests/ListRequest.json +++ b/java/core/src/test/resources/BrAPI-Schema/Requests/ListRequest.json @@ -82,6 +82,9 @@ "listType": { "$ref": "../BrAPI-Core/ListType.json#/$defs/ListType" } + }, + "brapi-metadata": { + "request": true } } }, diff --git a/java/core/src/test/resources/BrAPI-Schema/Requests/LocationRequest.json b/java/core/src/test/resources/BrAPI-Schema/Requests/LocationRequest.json index 33f46a0..6eac5b7 100644 --- a/java/core/src/test/resources/BrAPI-Schema/Requests/LocationRequest.json +++ b/java/core/src/test/resources/BrAPI-Schema/Requests/LocationRequest.json @@ -123,7 +123,10 @@ } } } - ] + ], + "brapi-metadata": { + "request": true + } } }, "$id": "https://brapi.org/Specification/BrAPI-Schema/Requests/LocationRequest.json", From 3e5c089f5fcea7ff7f09559efdb5dd2ff454e9a7 Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Wed, 12 Jun 2024 17:35:26 +1200 Subject: [PATCH 8/9] Updated schema and added more validation --- .../core/brapischema/BrAPISchemaReader.java | 116 +++- .../core/graphql/GraphQLGenerator.java | 2 +- .../core/model/BrAPIObjectProperty.java | 2 + .../core/model/BrAPIRelationshipType.java | 41 ++ .../core/openapi/OpenAPIGenerator.java | 5 +- .../schematools/core/utils/StringUtils.java | 5 +- .../brapischema/BrAPISchemaReaderTest.java | 46 +- .../BrAPI-Schema/BrAPI-Common/GeoJSON.json | 105 +-- .../BrAPI-Schema/BrAPI-Core/Contact.json | 57 ++ .../BrAPI-Schema/BrAPI-Core/DataLink.json | 72 +++ .../BrAPI-Schema/BrAPI-Core/Location.json | 24 +- .../BrAPI-Schema/BrAPI-Core/Person.json | 18 +- .../BrAPI-Schema/BrAPI-Core/Study.json | 108 +--- .../BrAPI-Schema/BrAPI-Core/Trial.json | 47 +- .../BrAPI-Genotyping/AlleleMatrix.json | 1 + .../BrAPI-Schema/BrAPI-Germplasm/Cross.json | 100 +-- .../BrAPI-Germplasm/CrossParent.json | 45 ++ .../BrAPI-Germplasm/CrossingProject.json | 46 +- .../BrAPI-Germplasm/Germplasm.json | 5 +- .../BrAPI-Germplasm/GermplasmAttribute.json | 601 +----------------- .../GermplasmAttributeValue.json | 4 +- .../BrAPI-Phenotyping/Method.json | 57 +- .../BrAPI-Phenotyping/OntologyReference.json | 61 ++ .../BrAPI-Schema/BrAPI-Phenotyping/Scale.json | 57 +- .../BrAPI-Schema/BrAPI-Phenotyping/Trait.json | 57 +- 25 files changed, 435 insertions(+), 1247 deletions(-) create mode 100644 java/core/src/main/java/org/brapi/schematools/core/model/BrAPIRelationshipType.java create mode 100644 java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Contact.json create mode 100644 java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/DataLink.json create mode 100644 java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossParent.json create mode 100644 java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/OntologyReference.json diff --git a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java index 5075c43..d73ec41 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java +++ b/java/core/src/main/java/org/brapi/schematools/core/brapischema/BrAPISchemaReader.java @@ -36,6 +36,7 @@ import static java.util.Collections.singletonList; import static org.brapi.schematools.core.response.Response.fail; import static org.brapi.schematools.core.response.Response.success; +import static org.brapi.schematools.core.utils.StringUtils.toSingular; /** * Utility class for reading BrAPI JSON Schema. @@ -57,35 +58,34 @@ public BrAPISchemaReader() { } /** - * Reads the schema module directories within a parent directory. + * Reads the schema module directories within a parent directory, and validates between schemas. * Each directory in the parent directory is a module and the JSON schemas in the directories are object types * * @param schemaDirectory the parent directory that holds all the module directories - * @return a list of BrAPIClass with one type per JSON Schema + * @return a response containing a list of BrAPIClass with one type per JSON Schema or validation errors * @throws BrAPISchemaReaderException if there is a problem reading the directories or JSON schemas */ - public List readDirectories(Path schemaDirectory) throws BrAPISchemaReaderException { + public Response> readDirectories(Path schemaDirectory) throws BrAPISchemaReaderException { try { - return dereferenceAllOfType(find(schemaDirectory, 3, this::schemaPathMatcher).flatMap(this::createBrAPISchemas).collect(Response.toList()). - getResultOrThrow(response -> new RuntimeException(response.getMessagesCombined(",")))); - } catch (IOException | RuntimeException e) { + return dereferenceAndValidate(find(schemaDirectory, 3, this::schemaPathMatcher).flatMap(this::createBrAPISchemas).collect(Response.toList())) ; + } catch (RuntimeException | IOException e) { throw new BrAPISchemaReaderException(e); } } /** * Reads a single object type from an JSON schema. If the JSON schema - * contain more than one type definition only the first is returned + * contain more than one type definition only the first is returned. There is + * no validation of referenced schemas * * @param schemaPath a JSON schema file * @param module the module in which the object resides - * @return the BrAPIClass for this schema + * @return a response containing the BrAPIClass for this schema or validation errors * @throws BrAPISchemaReaderException if there is a problem reading the JSON schema */ - public BrAPIClass readSchema(Path schemaPath, String module) throws BrAPISchemaReaderException { + public Response readSchema(Path schemaPath, String module) throws BrAPISchemaReaderException { try { - return createBrAPISchemas(schemaPath, module).collect(Response.toList()).mapResult(list -> list.get(0)). - getResultOrThrow(response -> new RuntimeException(response.getMessagesCombined(","))); + return createBrAPISchemas(schemaPath, module).collect(Response.toList()).mapResult(list -> list.get(0)) ; } catch (RuntimeException e) { throw new BrAPISchemaReaderException(e); } @@ -93,42 +93,104 @@ public BrAPIClass readSchema(Path schemaPath, String module) throws BrAPISchemaR /** * Reads a single object type from an JSON schema string. If the JSON schema - * contain more than one type definition only the first is returned + * contain more than one type definition only the first is returned. There is + * no validation of referenced schemas * * @param path the path of the schema is used to check references, if not supplied then validation is not performed * @param schema a JSON schema string * @param module the module in which the object resides - * @return the BrAPIType for this schema + * @return a response containing the BrAPIClass for this schema or validation errors * @throws BrAPISchemaReaderException if there is a problem reading the JSON schema */ - public BrAPIClass readSchema(Path path, String schema, String module) throws BrAPISchemaReaderException { + public Response 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)). - getResultOrThrow(response -> new RuntimeException( - String.format("Can not read schema at '%s' in module '%s' from '%s', due to '%s'", path, module, schema, response.getMessagesCombined(",")))); - } catch (RuntimeException | JsonProcessingException e) { + return createBrAPISchemas(path, objectMapper.readTree(schema), module).collect(Response.toList()).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 List dereferenceAllOfType(List types) { + private Response> dereferenceAndValidate(Response> types) { + + return types.mapResult(this::dereference).mapResultToResponse(this::validate) ; + } + + private List dereference(List types) { + Map typeMap = types.stream().collect(Collectors.toMap(BrAPIType::getName, Function.identity())); - List objectTypes = new ArrayList<>() ; + List brAPIClasses = new ArrayList<>() ; types.forEach(type -> { if (type instanceof BrAPIAllOfType brAPIAllOfType) { - objectTypes.add(BrAPIObjectType.builder(). + brAPIClasses.add(BrAPIObjectType.builder(). name(brAPIAllOfType.getName()). description(brAPIAllOfType.getDescription()). module(brAPIAllOfType.getModule()). properties(extractProperties(new ArrayList<>(), brAPIAllOfType, typeMap)).build()) ; } else { - objectTypes.add(type) ; + brAPIClasses.add(type) ; } }); - return objectTypes ; + return brAPIClasses ; + } + + private Response> validate(List brAPIClasses) { + Map classesMap = brAPIClasses.stream().collect(Collectors.toMap(BrAPIType::getName, Function.identity())); + + return brAPIClasses.stream().map(brAPIClass -> validateType(classesMap, brAPIClass).mapResult(t -> (BrAPIClass)t)).collect(Response.toList()) ; + } + + private Response validateType(final Map classesMap, BrAPIType brAPIType) { + + if (brAPIType instanceof BrAPIAllOfType brAPIAllOfType) { + return fail(Response.ErrorType.VALIDATION, String.format("Can not BrAPIAllOfType '%s' was not de-referenced", brAPIAllOfType.getName())) ; + } else if (brAPIType instanceof BrAPIOneOfType brAPIOneOfType) { + return brAPIOneOfType.getPossibleTypes().stream().map(possibleType -> validateType(classesMap, possibleType)).collect(Response.toList()). + merge(success(brAPIType)) ; + } else if (brAPIType instanceof BrAPIObjectType brAPIObjectType) { + return brAPIObjectType.getProperties().stream().map(property -> validateProperty(classesMap, brAPIObjectType, property)).collect(Response.toList()). + merge(success(brAPIType)) ; + } else { + return success(brAPIType) ; + } + } + + private Response validateProperty(Map classesMap, BrAPIObjectType brAPIObjectType, BrAPIObjectProperty property) { + if (property.getReferencedAttribute() != null) { + + BrAPIType type = unwrapType(property.getType()); + + BrAPIClass referencedType = classesMap.get(type.getName()) ; + + if (referencedType == null) { + return Response.fail(Response.ErrorType.VALIDATION, + String.format("Property '%s' in type '%s' has a Referenced Attribute '%s', but the referenced type '%s' is not available", + property.getName(), brAPIObjectType.getName(), property.getReferencedAttribute(), property.getType().getName())); + } + + if (referencedType instanceof BrAPIObjectType referencedObjectType) { + if (referencedObjectType.getProperties().stream().noneMatch(childProperty -> property.getReferencedAttribute().equals(childProperty.getName()))) { + return Response.fail(Response.ErrorType.VALIDATION, String.format("Property '%s' in type '%s' has a Referenced Attribute '%s', but the property does not exist in the referenced type '%s'", + property.getName(), brAPIObjectType.getName(), property.getReferencedAttribute(), referencedType.getName())); + } + } else { + return Response.fail(Response.ErrorType.VALIDATION, + String.format("Property '%s' in type '%s' has a Referenced Attribute '%s', but the referenced type '%s' is not a BrAPIObjectType", + property.getName(), brAPIObjectType.getName(), property.getReferencedAttribute(), referencedType.getName())); + } + } + + return Response.success(property) ; + } + + private BrAPIType unwrapType(BrAPIType type) { + if (type instanceof BrAPIArrayType brAPIArrayType) { + return unwrapType(brAPIArrayType.getItems()) ; + } + + return type ; } private List extractProperties(List properties, BrAPIType brAPIType, Map typeMap) { @@ -299,7 +361,7 @@ private Response createArrayType(Path path, JsonNode jsonNode, String BrAPIArrayType.BrAPIArrayTypeBuilder builder = BrAPIArrayType.builder().name(name); return findChildNode(jsonNode, "items", true). - mapResultToResponse(childNode -> createType(path, childNode, String.format("%sItem", name), module). + mapResultToResponse(childNode -> createType(path, childNode, toSingular(name), module). onSuccessDoWithResult(builder::items)). map(() -> success(builder.build())); } @@ -345,8 +407,14 @@ private Response createProperty(Path path, JsonNode jsonNod findString(jsonNode, "description", false). onSuccessDoWithResult(builder::description); + findString(jsonNode, "referencedAttribute", false). + onSuccessDoWithResult(builder::referencedAttribute); + return createType(path, jsonNode, StringUtils.toSentenceCase(name), module). onSuccessDoWithResult(builder::type). + mapOnCondition(jsonNode.has("relationshipType"), () -> findString(jsonNode, "relationshipType", true). + mapResultToResponse(BrAPIRelationshipType::fromNameOrLabel). + onSuccessDoWithResult(builder::relationshipType)). map(() -> success(builder.build())); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java index 8bcb75c..524e219 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java +++ b/java/core/src/main/java/org/brapi/schematools/core/graphql/GraphQLGenerator.java @@ -86,7 +86,7 @@ public Response generate(Path schemaDirectory) { public Response generate(Path schemaDirectory, GraphQLGeneratorMetadata metadata) { try { - return new Generator(options, metadata, schemaReader.readDirectories(schemaDirectory)).generate(); + return schemaReader.readDirectories(schemaDirectory).mapResultToResponse(brAPISchemas -> new Generator(options, metadata, brAPISchemas).generate()) ; } catch (BrAPISchemaReaderException e) { return fail(Response.ErrorType.VALIDATION, e.getMessage()); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java index 917407d..6151f1b 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIObjectProperty.java @@ -13,4 +13,6 @@ public class BrAPIObjectProperty { String description; BrAPIType type; boolean required; + String referencedAttribute; + BrAPIRelationshipType relationshipType; } diff --git a/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIRelationshipType.java b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIRelationshipType.java new file mode 100644 index 0000000..cf2d47d --- /dev/null +++ b/java/core/src/main/java/org/brapi/schematools/core/model/BrAPIRelationshipType.java @@ -0,0 +1,41 @@ +package org.brapi.schematools.core.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.brapi.schematools.core.response.Response; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +import static org.brapi.schematools.core.response.Response.fail; + +/** + * The type of relationship between types + */ +@Getter +@AllArgsConstructor +public enum BrAPIRelationshipType { + ONE_TO_ONE ("one-to-one"), + ONE_TO_MANY ("one-to-many"), + MANY_TO_ONE ("many-to-one"), + MANY_TO_MANY ("many-to-many") ; + + final String label ; + + public static Response fromNameOrLabel(final String nameOrLabel) { + return findByNameOrLabel(nameOrLabel) + .map(Response::success) + .orElseGet(() -> fail(Response.ErrorType.VALIDATION, String.format("No BrAPIRelationshipType found for name or label [%s]",nameOrLabel))); + } + + public static Response> fromNameOrLabels(List types) { + return types.stream().map(BrAPIRelationshipType::fromNameOrLabel).collect(Response.toList()) ; + } + + public static Optional findByNameOrLabel(final String nameOrLabel) { + return Stream.of(values()) + .filter(type -> type.name().equalsIgnoreCase(nameOrLabel) || type.getLabel().equalsIgnoreCase(nameOrLabel)) + .findAny(); + } +} diff --git a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java index 27760b3..1f163f9 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java +++ b/java/core/src/main/java/org/brapi/schematools/core/openapi/OpenAPIGenerator.java @@ -89,7 +89,10 @@ public Response> generate(Path schemaDirectory, Path componentsDir public Response> generate(Path schemaDirectory, Path componentsDirectory, OpenAPIGeneratorMetadata metadata) { try { - return new OpenAPIGenerator.Generator(options, metadata, schemaReader.readDirectories(schemaDirectory), componentsReader.readComponents(componentsDirectory)).generate(); + Components components = componentsReader.readComponents(componentsDirectory) ; + + return schemaReader.readDirectories(schemaDirectory).mapResultToResponse( + brAPISchemas -> new OpenAPIGenerator.Generator(options, metadata, brAPISchemas, components).generate()); } catch (BrAPISchemaReaderException | OpenAPIComponentsException e) { return fail(Response.ErrorType.VALIDATION, e.getMessage()); } diff --git a/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java b/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java index 36fd9f8..e4663db 100644 --- a/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java +++ b/java/core/src/main/java/org/brapi/schematools/core/utils/StringUtils.java @@ -30,14 +30,15 @@ public class StringUtils { replace("(.+[^aeiou])ies$").with("$1y"), replace("(.+)zes$").with("$1"), replace("([m|l])ice$").with("$1ouse"), - replace("matrices$").with("matrix"), + replace("(.+)matrices$").with("$1matrix"), replace("indices$").with("index"), replace("(.+[^aeiou])ices$").with("$1ice"), replace("(.*)ices$").with("$1ex"), replace("(octop|vir)i$").with("$1us"), replace("bases$").with("base"), replace("(.+(s|x|sh|ch))es$").with("$1"), - replace("(.+)s$").with("$1") + replace("(.+)s$").with("$1"), + replace("analysis$").with("analysis$") ); private static final List pluralisations = ImmutableList.of( diff --git a/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java b/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java index c4d97c8..cbcb13c 100644 --- a/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java +++ b/java/core/src/test/java/org/brapi/schematools/core/brapischema/BrAPISchemaReaderTest.java @@ -26,11 +26,13 @@ class BrAPISchemaReaderTest { void readDirectories() { try { - Map schemas = - new BrAPISchemaReader().readDirectories(Path.of(ClassLoader.getSystemResource("BrAPI-Schema").toURI())).stream().collect(Collectors.toMap(BrAPIClass::getName, Function.identity())); + Map schemas = new BrAPISchemaReader(). + readDirectories(Path.of(ClassLoader.getSystemResource("BrAPI-Schema").toURI())). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult().stream().collect(Collectors.toMap(BrAPIClass::getName, Function.identity())); assertNotNull(schemas); - assertEquals(52, schemas.size()); + assertEquals(54, schemas.size()); BrAPIClass trialSchema = schemas.get("Trial"); assertNotNull(trialSchema); @@ -82,8 +84,10 @@ void readDirectories() { @Test void readSchemaPath() { try { - BrAPIClass trialSchema = - new BrAPISchemaReader().readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/BrAPI-Core/Trial.json").toURI()), "BrAPI-Core"); + BrAPIClass trialSchema = new BrAPISchemaReader(). + readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/BrAPI-Core/Trial.json").toURI()), "BrAPI-Core"). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); assertNotNull(trialSchema); @@ -93,8 +97,11 @@ void readSchemaPath() { assertNotNull(trialSchema.getMetadata()); assertFalse(trialSchema.getMetadata().isPrimaryModel()); - BrAPIClass listTypeSchema = - new BrAPISchemaReader().readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/BrAPI-Core/ListType.json").toURI()), "BrAPI-Core"); + BrAPIClass listTypeSchema = new BrAPISchemaReader(). + readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/BrAPI-Core/ListType.json").toURI()), "BrAPI-Core"). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); + assertNotNull(listTypeSchema); @@ -103,8 +110,10 @@ void readSchemaPath() { assertEquals("BrAPI-Core", trialSchema.getModule()); assertNull(listTypeSchema.getMetadata()); - BrAPIClass listRequest = - new BrAPISchemaReader().readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/Requests/ListRequest.json").toURI()), null); + BrAPIClass listRequest = new BrAPISchemaReader(). + readSchema(Path.of(ClassLoader.getSystemResource("BrAPI-Schema/Requests/ListRequest.json").toURI()), null). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); assertNotNull(listRequest); assertEquals("ListRequest", listRequest.getName()); @@ -122,8 +131,11 @@ void readSchemaString() { try { Path path = Paths.get(Objects.requireNonNull(this.getClass().getResource("/BrAPI-Schema/BrAPI-Core/Trial.json")).toURI()); - BrAPIClass trialSchema = - new BrAPISchemaReader().readSchema(path, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), "BrAPI-Core"); + BrAPIClass trialSchema = new BrAPISchemaReader(). + readSchema(path, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), "BrAPI-Core"). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); + assertNotNull(trialSchema); @@ -135,8 +147,10 @@ void readSchemaString() { path = Paths.get(Objects.requireNonNull(this.getClass().getResource("/BrAPI-Schema/BrAPI-Core/ListType.json")).toURI()); - BrAPIClass listTypeSchema = - new BrAPISchemaReader().readSchema(path, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), "BrAPI-Core"); + BrAPIClass listTypeSchema = new BrAPISchemaReader(). + readSchema(path, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), "BrAPI-Core"). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); assertNotNull(listTypeSchema); @@ -147,8 +161,10 @@ void readSchemaString() { path = Paths.get(Objects.requireNonNull(this.getClass().getResource("/BrAPI-Schema/Requests/ListRequest.json")).toURI()); - BrAPIClass listRequest = - new BrAPISchemaReader().readSchema(null, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), null); + BrAPIClass listRequest = new BrAPISchemaReader(). + readSchema(null, String.join("\n", Files.readAllLines(path, Charset.defaultCharset())), null). + onFailDoWithResponse(response -> fail(response.getMessagesCombined(","))). + getResult(); assertNotNull(listRequest); assertEquals("ListRequest", listRequest.getName()); diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Common/GeoJSON.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Common/GeoJSON.json index 20b1212..f4ff5c1 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Common/GeoJSON.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Common/GeoJSON.json @@ -6,32 +6,8 @@ "description": "One geometry as defined by GeoJSON (RFC 7946). All coordinates are decimal values on the WGS84 geographic coordinate reference system.\n\nCopied from RFC 7946 Section 3.1.1\n\nA position is an array of numbers. There MUST be two or more elements. The first two elements are longitude and latitude, or\neasting and northing, precisely in that order and using decimal numbers. Altitude or elevation MAY be included as an optional third element.", "properties": { "geometry": { - "title": "GeoJSON Geometry", - "type": "object", "description": "A geometry as defined by GeoJSON (RFC 7946). In this context, only Point or Polygon geometry are allowed.", - "oneOf": [ - { - "$ref": "#/$defs/PointGeometry" - }, - { - "$ref": "#/$defs/PolygonGeometry" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "Point": "#/$defs/PointGeometry", - "Polygon": "#/$defs/PolygonGeometry" - } - }, - "example": { - "coordinates": [ - -76.506042, - 42.417373, - 123 - ], - "type": "Point" - } + "$ref": "GeoJSONGeometry.json#/$defs/GeoJSONGeometry" }, "type": { "type": "string", @@ -40,85 +16,6 @@ "description": "The literal string \"Feature\"" } } - }, - "PointGeometry": { - "type": "object", - "description": "Copied from RFC 7946 Section 3.1.1\n\nA position is an array of numbers. There MUST be two or more elements. The first two elements are longitude and latitude, or\neasting and northing, precisely in that order and using decimal numbers. Altitude or elevation MAY be included as an optional third element.", - "required": [ - "type", - "coordinates" - ], - "properties": { - "coordinates": { - "items": { - "type": "number" - }, - "minItems": 2, - "type": "array" - }, - "type": { - "type": "string", - "default": "Point", - "example": "Point", - "description": "The literal string \"Point\"" - } - } - }, - "PolygonGeometry": { - "type": "object", - "description": "An array of Linear Rings. Each Linear Ring is an array of Points. \n\nA Point is an array of numbers. There MUST be two or more elements. The first two elements are longitude and latitude, or\neasting and northing, precisely in that order and using decimal numbers. Altitude or elevation MAY be included as an optional third element.", - "required": [ - "type", - "coordinates" - ], - "properties": { - "coordinates": { - "description": "An array of linear rings", - "items": { - "description": "An array of at least four positions where the first equals the last", - "items": { - "items": { - "type": "number" - }, - "minItems": 2, - "type": "array" - }, - "minItems": 4, - "type": "array" - }, - "type": "array", - "example": [ - [ - [ - -77.456654, - 42.241133, - 494 - ], - [ - -75.414133, - 41.508282, - 571 - ], - [ - -76.506042, - 42.417373, - 123 - ], - [ - -77.456654, - 42.241133, - 346 - ] - ] - ] - }, - "type": { - "type": "string", - "default": "Polygon", - "example": "Polygon", - "description": "The literal string \"Polygon\"" - } - } } }, "$id": "https://brapi.org/Specification/BrAPI-Schema/BrAPI-Common/GeoJSON.json", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Contact.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Contact.json new file mode 100644 index 0000000..e72571c --- /dev/null +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Contact.json @@ -0,0 +1,57 @@ +{ + "$defs": { + "Contact": { + "properties": { + "contactDbId": { + "description": "The ID which uniquely identifies this contact\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", + "type": "string" + }, + "email": { + "description": "The contacts email address\n\nMIAPPE V1.1 (DM-32) Person email - The electronic mail address of the person.", + "type": [ + "null", + "string" + ] + }, + "instituteName": { + "description": "The name of the institution which this contact is part of\n\nMIAPPE V1.1 (DM-35) Person affiliation - The institution the person belongs to", + "type": [ + "null", + "string" + ] + }, + "name": { + "description": "The full name of this contact person\n\nMIAPPE V1.1 (DM-31) Person name - The name of the person (either full name or as used in scientific publications)", + "type": [ + "null", + "string" + ] + }, + "orcid": { + "description": "The Open Researcher and Contributor ID for this contact person (orcid.org)\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", + "type": [ + "null", + "string" + ] + }, + "type": { + "description": "The type of person this contact represents (ex: Coordinator, Scientist, PI, etc.)\n\nMIAPPE V1.1 (DM-34) Person role - Type of contribution of the person to the investigation", + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "contactDbId" + ], + "type": "object", + "title": "Contact", + "brapi-metadata": { + "primaryModel": false + } + } + }, + "$id": "https://brapi.org/Specification/BrAPI-Schema/BrAPI-Core/Contact.json", + "$schema": "http://json-schema.org/draft/2020-12/schema" +} \ No newline at end of file diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/DataLink.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/DataLink.json new file mode 100644 index 0000000..d00aa68 --- /dev/null +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/DataLink.json @@ -0,0 +1,72 @@ +{ + "$defs": { + "DataLink": { + "properties": { + "dataFormat": { + "description": "The structure of the data within a file. For example - VCF, table, image archive, multispectral image archives in EDAM ontology (used in Galaxy)\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", + "type": [ + "null", + "string" + ] + }, + "description": { + "description": "The general description of this data link\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", + "type": [ + "null", + "string" + ] + }, + "fileFormat": { + "description": "The MIME type of the file (ie text/csv, application/excel, application/zip).\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", + "type": [ + "null", + "string" + ] + }, + "name": { + "description": "The name of the external data link\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", + "type": [ + "null", + "string" + ] + }, + "provenance": { + "description": "The description of the origin or ownership of this linked data. Could be a formal reference to software, method, or workflow.", + "type": [ + "null", + "string" + ] + }, + "scientificType": { + "description": "The general type of data. For example- Genotyping, Phenotyping raw data, Phenotyping reduced data, Environmental, etc", + "type": [ + "null", + "string" + ] + }, + "url": { + "description": "URL describing the location of this data file to view or download\n\nMIAPPE V1.1 (DM-37) Data file link - Link to the data file (or digital object) in a public database or in a persistent institutional repository; or identifier of the data file when submitted together with the MIAPPE submission.", + "format": "uri", + "type": [ + "null", + "string" + ] + }, + "version": { + "description": "The version number for this data \n\nMIAPPE V1.1 (DM-39) Data file version - The version of the dataset (the actual data).", + "type": [ + "null", + "string" + ] + } + }, + "title": "DataLink", + "type": "object", + "brapi-metadata": { + "primaryModel": false + } + } + }, + "$id": "https://brapi.org/Specification/BrAPI-Schema/BrAPI-Core/DataLink.json", + "$schema": "http://json-schema.org/draft/2020-12/schema" +} \ No newline at end of file diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Location.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Location.json index aea83b9..12b5f0f 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Location.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Location.json @@ -29,25 +29,7 @@ }, "coordinates": { "description": "One geometry as defined by GeoJSON (RFC 7946). All coordinates are decimal values on the WGS84 geographic coordinate reference system.\n\nCopied from RFC 7946 Section 3.1.1\n\nA position is an array of numbers. There MUST be two or more elements. The first two elements are longitude and latitude, or\neasting and northing, precisely in that order and using decimal numbers. Altitude or elevation MAY be included as an optional third element.", - "properties": { - "geometry": { - "description": "A geometry as defined by GeoJSON (RFC 7946). In this context, only Point or Polygon geometry are allowed.", - "$ref": "../BrAPI-Common/GeoJSONGeometry.json#/$defs/GeoJSONGeometry" - }, - "type": { - "default": "Feature", - "description": "The literal string \"Feature\"", - "type": [ - "null", - "string" - ] - } - }, - "title": "GeoJSON", - "type": [ - "null", - "object" - ] + "$ref": "../BrAPI-Common/GeoJSON.json#/$defs/GeoJSON" }, "countryCode": { "description": "[ISO_3166-1_alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) spec\n
MIAPPE V1.1 (DM-17) Geographic location (country) - The country where the experiment took place, either as a full name or preferably as a 2-letter code.'", @@ -181,7 +163,7 @@ ] }, "seedLots": { - "title": "seedLots", + "title": "SeedLots", "description": "seedLots", "referencedAttribute": "location", "relationshipType": "one-to-many", @@ -195,7 +177,7 @@ ] }, "observationUnits": { - "title": "observationUnits", + "title": "ObservationUnits", "description": "observationUnits", "referencedAttribute": "location", "relationshipType": "one-to-many", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Person.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Person.json index 1f342de..c7d8e34 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Person.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Person.json @@ -23,23 +23,7 @@ "externalReferences": { "description": "An array of external reference ids. These are references to this piece of data in an external system. Could be a simple string or a URI.", "items": { - "properties": { - "referenceId": { - "description": "The external reference ID. Could be a simple string or a URI.", - "type": [ - "null", - "string" - ] - }, - "referenceSource": { - "description": "An identifier for the source system or database of this reference", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" + "$ref": "../BrAPI-Common/ExternalReference.json#/$defs/ExternalReference" }, "title": "ExternalReferences", "type": [ diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Study.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Study.json index 422d5e1..8f060ca 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Study.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Study.json @@ -22,52 +22,9 @@ }, "contacts": { "description": "List of contact entities associated with this study", + "relationshipType": "many-to-many", "items": { - "properties": { - "contactDbId": { - "description": "The ID which uniquely identifies this contact\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", - "type": "string" - }, - "email": { - "description": "The contacts email address\n\nMIAPPE V1.1 (DM-32) Person email - The electronic mail address of the person.", - "type": [ - "null", - "string" - ] - }, - "instituteName": { - "description": "The name of the institution which this contact is part of\n\nMIAPPE V1.1 (DM-35) Person affiliation - The institution the person belongs to", - "type": [ - "null", - "string" - ] - }, - "name": { - "description": "The full name of this contact person\n\nMIAPPE V1.1 (DM-31) Person name - The name of the person (either full name or as used in scientific publications)", - "type": [ - "null", - "string" - ] - }, - "orcid": { - "description": "The Open Researcher and Contributor ID for this contact person (orcid.org)\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", - "type": [ - "null", - "string" - ] - }, - "type": { - "description": "The type of person this contact represents (ex: Coordinator, Scientist, PI, etc.)\n\nMIAPPE V1.1 (DM-34) Person role - Type of contribution of the person to the investigation", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "contactDbId" - ], - "type": "object" + "$ref": "Contact.json#/$defs/Contact" }, "type": [ "null", @@ -84,66 +41,7 @@ "dataLinks": { "description": "List of links to extra data files associated with this study. Extra data could include notes, images, and reference data.", "items": { - "properties": { - "dataFormat": { - "description": "The structure of the data within a file. For example - VCF, table, image archive, multispectral image archives in EDAM ontology (used in Galaxy)\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", - "type": [ - "null", - "string" - ] - }, - "description": { - "description": "The general description of this data link\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", - "type": [ - "null", - "string" - ] - }, - "fileFormat": { - "description": "The MIME type of the file (ie text/csv, application/excel, application/zip).\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", - "type": [ - "null", - "string" - ] - }, - "name": { - "description": "The name of the external data link\n\nMIAPPE V1.1 (DM-38) Data file description - Description of the format of the data file. May be a standard file format name, or a description of organization of the data in a tabular file.", - "type": [ - "null", - "string" - ] - }, - "provenance": { - "description": "The description of the origin or ownership of this linked data. Could be a formal reference to software, method, or workflow.", - "type": [ - "null", - "string" - ] - }, - "scientificType": { - "description": "The general type of data. For example- Genotyping, Phenotyping raw data, Phenotyping reduced data, Environmental, etc", - "type": [ - "null", - "string" - ] - }, - "url": { - "description": "URL describing the location of this data file to view or download\n\nMIAPPE V1.1 (DM-37) Data file link - Link to the data file (or digital object) in a public database or in a persistent institutional repository; or identifier of the data file when submitted together with the MIAPPE submission.", - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "version": { - "description": "The version number for this data \n\nMIAPPE V1.1 (DM-39) Data file version - The version of the dataset (the actual data).", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" + "$ref": "DataLink.json#/$defs/DataLink" }, "type": [ "null", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Trial.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Trial.json index 7d7e721..863a68c 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Trial.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Core/Trial.json @@ -22,52 +22,9 @@ }, "contacts": { "description": "List of contact entities associated with this trial", + "relationshipType": "many-to-many", "items": { - "properties": { - "contactDbId": { - "description": "The ID which uniquely identifies this contact\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", - "type": "string" - }, - "email": { - "description": "The contacts email address\n\nMIAPPE V1.1 (DM-32) Person email - The electronic mail address of the person.", - "type": [ - "null", - "string" - ] - }, - "instituteName": { - "description": "The name of the institution which this contact is part of\n\nMIAPPE V1.1 (DM-35) Person affiliation - The institution the person belongs to", - "type": [ - "null", - "string" - ] - }, - "name": { - "description": "The full name of this contact person\n\nMIAPPE V1.1 (DM-31) Person name - The name of the person (either full name or as used in scientific publications)", - "type": [ - "null", - "string" - ] - }, - "orcid": { - "description": "The Open Researcher and Contributor ID for this contact person (orcid.org)\n\nMIAPPE V1.1 (DM-33) Person ID - An identifier for the data submitter. If that submitter is an individual, ORCID identifiers are recommended.", - "type": [ - "null", - "string" - ] - }, - "type": { - "description": "The type of person this contact represents (ex: Coordinator, Scientist, PI, etc.)\n\nMIAPPE V1.1 (DM-34) Person role - Type of contribution of the person to the investigation", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "contactDbId" - ], - "type": "object" + "$ref": "Contact.json#/$defs/Contact" }, "type": [ "null", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Genotyping/AlleleMatrix.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Genotyping/AlleleMatrix.json index 36f05ab..4cc6e67 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Genotyping/AlleleMatrix.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Genotyping/AlleleMatrix.json @@ -76,6 +76,7 @@ }, "pagination": { "description": "Pagination for the matrix", + "title": "MatrixPage", "items": { "properties": { "dimension": { diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Cross.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Cross.json index 3e47cb2..cda37bf 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Cross.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Cross.json @@ -79,104 +79,12 @@ ] }, "parent1": { - "properties": { - "germplasmDbId": { - "description": "the unique identifier for a germplasm", - "type": [ - "null", - "string" - ] - }, - "germplasmName": { - "description": "the human readable name for a germplasm", - "type": [ - "null", - "string" - ] - }, - "observationUnitDbId": { - "description": "the unique identifier for an observation unit", - "type": [ - "null", - "string" - ] - }, - "observationUnitName": { - "description": "the human readable name for an observation unit", - "type": [ - "null", - "string" - ] - }, - "parentType": { - "description": "The type of parent ex. 'MALE', 'FEMALE', 'SELF', 'POPULATION', etc.", - "enum": [ - "MALE", - "FEMALE", - "SELF", - "POPULATION", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": [ - "null", - "object" - ] + "$ref": "CrossParent.json#/$defs/CrossParent", + "description": "the first parent used in the cross" }, "parent2": { - "properties": { - "germplasmDbId": { - "description": "the unique identifier for a germplasm", - "type": [ - "null", - "string" - ] - }, - "germplasmName": { - "description": "the human readable name for a germplasm", - "type": [ - "null", - "string" - ] - }, - "observationUnitDbId": { - "description": "the unique identifier for an observation unit", - "type": [ - "null", - "string" - ] - }, - "observationUnitName": { - "description": "the human readable name for an observation unit", - "type": [ - "null", - "string" - ] - }, - "parentType": { - "description": "The type of parent ex. 'MALE', 'FEMALE', 'SELF', 'POPULATION', etc.", - "enum": [ - "MALE", - "FEMALE", - "SELF", - "POPULATION", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": [ - "null", - "object" - ] + "$ref": "CrossParent.json#/$defs/CrossParent", + "description": "the second parent used in the cross" }, "plannedCross": { "$ref": "PlannedCross.json#/$defs/PlannedCross", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossParent.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossParent.json new file mode 100644 index 0000000..daa4e7f --- /dev/null +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossParent.json @@ -0,0 +1,45 @@ +{ + "$defs": { + "CrossParent": { + "properties": { + "germplasm": { + "description": "the germplasm of the cross parent", + "$ref": "Germplasm.json#/$defs/Germplasm", + "type": [ + "null", + "string" + ] + }, + "observationUnit": { + "description": "the Observation Unit of the cross parent", + "$ref": "../BrAPI-Phenotyping/ObservationUnit.json#/$defs/ObservationUnit", + "type": [ + "null", + "string" + ] + }, + "parentType": { + "description": "The type of parent ex. 'MALE', 'FEMALE', 'SELF', 'POPULATION', etc.", + "enum": [ + "MALE", + "FEMALE", + "SELF", + "POPULATION", + null + ], + "type": [ + "null", + "string" + ] + } + }, + "title": "CrossParent", + "type": "object", + "brapi-metadata": { + "primaryModel": false + } + } + }, + "$id": "https://brapi.org/Specification/BrAPI-Schema/BrAPI-Germplasm/CrossParent.json", + "$schema": "http://json-schema.org/draft/2020-12/schema" +} \ No newline at end of file diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossingProject.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossingProject.json index bf2e26f..7b676e7 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossingProject.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/CrossingProject.json @@ -42,51 +42,7 @@ "potentialParents": { "description": "A list of all the potential parents in the crossing block, available in the crossing project\n
If the parameter 'includePotentialParents' is false, the array 'potentialParents' should be empty, null, or excluded from the response object.", "items": { - "properties": { - "germplasmDbId": { - "description": "the unique identifier for a germplasm", - "type": [ - "null", - "string" - ] - }, - "germplasmName": { - "description": "the human readable name for a germplasm", - "type": [ - "null", - "string" - ] - }, - "observationUnitDbId": { - "description": "the unique identifier for an observation unit", - "type": [ - "null", - "string" - ] - }, - "observationUnitName": { - "description": "the human readable name for an observation unit", - "type": [ - "null", - "string" - ] - }, - "parentType": { - "description": "The type of parent ex. 'MALE', 'FEMALE', 'SELF', 'POPULATION', etc.", - "enum": [ - "MALE", - "FEMALE", - "SELF", - "POPULATION", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" + "$ref": "CrossParent.json#/$defs/CrossParent" }, "type": [ "null", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Germplasm.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Germplasm.json index 74d66eb..80a9986 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Germplasm.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/Germplasm.json @@ -390,7 +390,6 @@ "progenyPedigreeNodes": { "title": "progenyPedigreeNodes", "description": "progenyPedigreeNodes", - "referencedAttribute": "parentGermplasm", "relationshipType": "one-to-many", "items": { "$ref": "PedigreeNode.json#/$defs/PedigreeNode", @@ -404,7 +403,6 @@ "parentPedigreeNodes": { "title": "parentPedigreeNodes", "description": "parentPedigreeNodes", - "referencedAttribute": "progenyGermplasm", "relationshipType": "one-to-many", "items": { "$ref": "PedigreeNode.json#/$defs/PedigreeNode", @@ -416,9 +414,8 @@ ] }, "siblingPedigreeNodes": { - "title": "siblingPedigreeNodes", + "title": "SiblingPedigreeNodes", "description": "siblingPedigreeNodes", - "referencedAttribute": "siblingGermplasm", "relationshipType": "one-to-many", "items": { "$ref": "PedigreeNode.json#/$defs/PedigreeNode", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttribute.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttribute.json index 0f2d517..80d8946 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttribute.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttribute.json @@ -104,413 +104,15 @@ }, "method": { "description": "A description of the way an Observation should be collected. \n
For example, an ObservationVariable might be defined with a Trait of \"plant height\", a Scale of \"meters\", and a Method of \"tape measure\". This variable would be distinct from a variable with the Method \"estimation\" or \"drone image processing\". ", - "properties": { - "additionalInfo": { - "additionalProperties": { - "type": "string" - }, - "description": "A free space containing any additional information related to a particular object. A data source may provide any JSON object, unrestricted by the BrAPI specification.", - "type": [ - "null", - "object" - ] - }, - "bibliographicalReference": { - "description": "Bibliographical reference describing the method.\n
MIAPPE V1.1 (DM-91) Reference associated to the method - URI/DOI of reference describing the method.", - "type": [ - "null", - "string" - ] - }, - "description": { - "description": "Method description\n
MIAPPE V1.1 (DM-90) Method description - Textual description of the method, which may extend a method defined in an external reference with specific parameters, e.g. growth stage, inoculation precise organ (leaf number)", - "type": [ - "null", - "string" - ] - }, - "externalReferences": { - "description": "An array of external reference ids. These are references to this piece of data in an external system. Could be a simple string or a URI.", - "items": { - "properties": { - "referenceId": { - "description": "The external reference ID. Could be a simple string or a URI.", - "type": [ - "null", - "string" - ] - }, - "referenceSource": { - "description": "An identifier for the source system or database of this reference", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "title": "ExternalReferences", - "type": [ - "null", - "array" - ] - }, - "formula": { - "description": "For computational methods i.e., when the method consists in assessing the trait by computing measurements, write the generic formula used for the calculation", - "type": [ - "null", - "string" - ] - }, - "methodClass": { - "description": "Method class (examples: \"Measurement\", \"Counting\", \"Estimation\", \"Computation\", etc.)", - "type": [ - "null", - "string" - ] - }, - "methodDbId": { - "description": "Method unique identifier", - "type": [ - "null", - "string" - ] - }, - "methodName": { - "description": "Human readable name for the method\n
MIAPPE V1.1 (DM-88) Method Name of the method of observation", - "type": "string" - }, - "methodPUI": { - "description": "The Permanent Unique Identifier of a Method, usually in the form of a URI", - "type": [ - "null", - "string" - ] - }, - "ontologyReference": { - "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] - } - }, - "required": [ - "methodName" - ], - "type": "object" + "$ref": "../BrAPI-Phenotyping/Method.json#/$defs/Method" }, "ontologyReference": { "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] + "$ref": "../BrAPI-Phenotyping/OntologyReference.json#/$defs/OntologyReference" }, "scale": { "description": "A Scale describes the units and acceptable values for an ObservationVariable. \n
For example, an ObservationVariable might be defined with a Trait of \"plant height\", a Scale of \"meters\", and a Method of \"tape measure\". This variable would be distinct from a variable with the Scale \"inches\" or \"pixels\".", - "properties": { - "additionalInfo": { - "additionalProperties": { - "type": "string" - }, - "description": "A free space containing any additional information related to a particular object. A data source may provide any JSON object, unrestricted by the BrAPI specification.", - "type": [ - "null", - "object" - ] - }, - "dataType": { - "description": "

Class of the scale, entries can be

\n

\"Code\" - This scale class is exceptionally used to express complex traits. Code is a nominal scale that combines the expressions of the different traits composing the complex trait. For example a severity trait might be expressed by a 2 digit and 2 character code. The first 2 digits are the percentage of the plant covered by a fungus and the 2 characters refer to the delay in development, e.g. \"75VD\" means \"75 %\" of the plant is infected and the plant is very delayed.

\n

\"Date\" - The date class is for events expressed in a time format, See ISO 8601

\n

\"Duration\" - The Duration class is for time elapsed between two events expressed in a time format, e.g. days, hours, months

\n

\"Nominal\" - Categorical scale that can take one of a limited and fixed number of categories. There is no intrinsic ordering to the categories

\n

\"Numerical\" - Numerical scales express the trait with real numbers. The numerical scale defines the unit e.g. centimeter, ton per hectare, branches

\n

\"Ordinal\" - Ordinal scales are scales composed of ordered categories

\n

\"Text\" - A free text is used to express the trait.

", - "enum": [ - "Code", - "Date", - "Duration", - "Nominal", - "Numerical", - "Ordinal", - "Text", - null - ], - "type": [ - "null", - "string" - ] - }, - "decimalPlaces": { - "description": "For numerical, number of decimal places to be reported", - "type": [ - "null", - "integer" - ] - }, - "externalReferences": { - "description": "An array of external reference ids. These are references to this piece of data in an external system. Could be a simple string or a URI.", - "items": { - "properties": { - "referenceId": { - "description": "The external reference ID. Could be a simple string or a URI.", - "type": [ - "null", - "string" - ] - }, - "referenceSource": { - "description": "An identifier for the source system or database of this reference", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "title": "ExternalReferences", - "type": [ - "null", - "array" - ] - }, - "ontologyReference": { - "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] - }, - "scaleDbId": { - "description": "Unique identifier of the scale. If left blank, the upload system will automatically generate a scale ID.", - "type": "string" - }, - "scaleName": { - "description": "Name of the scale\n
MIAPPE V1.1 (DM-92) Scale Name of the scale associated with the variable", - "type": "string" - }, - "scalePUI": { - "description": "The Permanent Unique Identifier of a Scale, usually in the form of a URI", - "type": [ - "null", - "string" - ] - }, - "units": { - "description": "This field can be used to describe the units used for this scale. This should be the abbreviated \nform of the units, intended to be displayed with every value using this scale. Usually this only \napplies when `dataType` is Numeric, but could also be included for other dataTypes when applicable.", - "type": [ - "null", - "string" - ] - }, - "validValues": { - "properties": { - "categories": { - "description": "List of possible values with optional labels", - "items": { - "properties": { - "label": { - "description": "A text label for a category", - "type": [ - "null", - "string" - ] - }, - "value": { - "description": "The actual value for a category", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "maximumValue": { - "description": "Maximum value for numerical, date, and time scales. Typically used for data capture control and QC.", - "type": [ - "null", - "string" - ] - }, - "minimumValue": { - "description": "Minimum value for numerical, date, and time scales. Typically used for data capture control and QC.", - "type": [ - "null", - "string" - ] - } - }, - "type": [ - "null", - "object" - ] - } - }, - "required": [ - "scaleDbId", - "scaleName" - ], - "type": "object" + "$ref": "../BrAPI-Phenotyping/Scale.json#/$defs/Scale" }, "scientist": { "description": "Name of scientist submitting the variable.", @@ -546,202 +148,7 @@ }, "trait": { "description": "A Trait describes what property is being observed. \n
For example, an ObservationVariable might be defined with a Trait of \"plant height\", a Scale of \"meters\", and a Method of \"tape measure\". This variable would be distinct from a variable with the Trait \"Leaf length\" or \"Flower height\". ", - "properties": { - "additionalInfo": { - "additionalProperties": { - "type": "string" - }, - "description": "A free space containing any additional information related to a particular object. A data source may provide any JSON object, unrestricted by the BrAPI specification.", - "type": [ - "null", - "object" - ] - }, - "alternativeAbbreviations": { - "description": "A list of shortened, human readable, names for a Trait. These abbreviations are acceptable alternatives to the mainAbbreviation and do not need to follow any formatting convention.", - "items": { - "type": "string" - }, - "type": [ - "null", - "array" - ] - }, - "attribute": { - "description": "A trait can be decomposed as \"Trait\" = \"Entity\" + \"Attribute\", the attribute is the observed feature (or characteristic) of the entity e.g., for \"grain colour\", attribute = \"colour\"", - "type": [ - "null", - "string" - ] - }, - "attributePUI": { - "description": "The Permanent Unique Identifier of a Trait Attribute, usually in the form of a URI\n
A trait can be decomposed as \"Trait\" = \"Entity\" + \"Attribute\", the attribute is the observed feature (or characteristic) of the entity e.g., for \"grain colour\", attribute = \"colour\"", - "type": [ - "null", - "string" - ] - }, - "entity": { - "description": "A trait can be decomposed as \"Trait\" = \"Entity\" + \"Attribute\", the entity is the part of the plant that the trait refers to e.g., for \"grain colour\", entity = \"grain\"", - "type": [ - "null", - "string" - ] - }, - "entityPUI": { - "description": "The Permanent Unique Identifier of a Trait Entity, usually in the form of a URI\n
A Trait can be decomposed as \"Trait\" = \"Entity\" + \"Attribute\", the Entity is the part of the plant that the trait refers to e.g., for \"grain colour\", entity = \"grain\" ", - "type": [ - "null", - "string" - ] - }, - "externalReferences": { - "description": "An array of external reference ids. These are references to this piece of data in an external system. Could be a simple string or a URI.", - "items": { - "properties": { - "referenceId": { - "description": "The external reference ID. Could be a simple string or a URI.", - "type": [ - "null", - "string" - ] - }, - "referenceSource": { - "description": "An identifier for the source system or database of this reference", - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "title": "ExternalReferences", - "type": [ - "null", - "array" - ] - }, - "mainAbbreviation": { - "description": "A shortened version of the human readable name for a Trait", - "type": [ - "null", - "string" - ] - }, - "ontologyReference": { - "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] - }, - "status": { - "description": "Trait status (examples: \"recommended\", \"obsolete\", \"legacy\", etc.)", - "type": [ - "null", - "string" - ] - }, - "synonyms": { - "description": "Other trait names", - "items": { - "type": "string" - }, - "type": [ - "null", - "array" - ] - }, - "traitClass": { - "description": "A classification to describe the type of trait and the context it should be considered in.\n
examples- \"morphological\", \"phenological\", \"agronomical\", \"physiological\", \"abiotic stress\", \"biotic stress\", \"biochemical\", \"quality traits\", \"fertility\", etc.", - "type": [ - "null", - "string" - ] - }, - "traitDbId": { - "description": "The ID which uniquely identifies a trait", - "type": [ - "null", - "string" - ] - }, - "traitDescription": { - "description": "The description of a trait", - "type": [ - "null", - "string" - ] - }, - "traitName": { - "description": "The human readable name of a trait\n
MIAPPE V1.1 (DM-86) Trait - Name of the (plant or environmental) trait under observation", - "type": "string" - }, - "traitPUI": { - "description": "The Permanent Unique Identifier of a Trait, usually in the form of a URI", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "traitName" - ], - "type": "object" + "$ref": "../BrAPI-Phenotyping/Trait.json#/$defs/Trait" }, "attributeValues": { "title": "attributeValues", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttributeValue.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttributeValue.json index a721854..d222fa1 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttributeValue.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Germplasm/GermplasmAttributeValue.json @@ -9,7 +9,7 @@ "attribute": { "$ref": "GermplasmAttribute.json#/$defs/GermplasmAttribute", "description": "The ID which uniquely identifies this attribute within the given database server", - "referencedAttribute": "germplasmAttributeValues", + "referencedAttribute": "attributeValues", "relationshipType": "many-to-one" }, "attributeValueDbId": { @@ -38,7 +38,7 @@ "germplasm": { "$ref": "Germplasm.json#/$defs/Germplasm", "description": "The ID which uniquely identifies a germplasm within the given database server", - "referencedAttribute": "germplasmAttributeValues", + "referencedAttribute": "attributeValues", "relationshipType": "many-to-one" }, "value": { diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Method.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Method.json index 2fda39b..29700d6 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Method.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Method.json @@ -65,62 +65,7 @@ }, "ontologyReference": { "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] + "$ref": "../BrAPI-Phenotyping/OntologyReference.json#/$defs/OntologyReference" } }, "required": [ diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/OntologyReference.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/OntologyReference.json new file mode 100644 index 0000000..575aab6 --- /dev/null +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/OntologyReference.json @@ -0,0 +1,61 @@ +{ + "$defs": { + "OntologyReference": { + "properties": { + "documentationLinks": { + "description": "links to various ontology documentation", + "items": { + "properties": { + "URL": { + "format": "uri", + "type": [ + "null", + "string" + ] + }, + "type": { + "enum": [ + "OBO", + "RDF", + "WEBPAGE", + null + ], + "type": [ + "null", + "string" + ] + } + }, + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "ontology": { + "description": "The Ontology for this reference", + "$ref": "../BrAPI-Phenotyping/Ontology.json#/$defs/Ontology" + }, + "version": { + "description": "Ontology version (no specific format)", + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "ontologyName", + "ontologyDbId" + ], + "title": "OntologyReference", + "type": "object", + "brapi-metadata": { + "primaryModel": false + } + } + }, + "$id": "https://brapi.org/Specification/BrAPI-Schema/BrAPI-Phenotyping/OntologyReference.json", + "$schema": "http://json-schema.org/draft/2020-12/schema" +} \ No newline at end of file diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Scale.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Scale.json index b0de012..a396918 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Scale.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Scale.json @@ -43,62 +43,7 @@ }, "ontologyReference": { "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] + "$ref": "../BrAPI-Phenotyping/OntologyReference.json#/$defs/OntologyReference" }, "scaleDbId": { "description": "Unique identifier of the scale. If left blank, the upload system will automatically generate a scale ID.", diff --git a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Trait.json b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Trait.json index 1634c43..0643633 100644 --- a/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Trait.json +++ b/java/core/src/test/resources/BrAPI-Schema/BrAPI-Phenotyping/Trait.json @@ -64,62 +64,7 @@ }, "ontologyReference": { "description": "MIAPPE V1.1\n\n(DM-85) Variable accession number - Accession number of the variable in the Crop Ontology\n\n(DM-87) Trait accession number - Accession number of the trait in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-89) Method accession number - Accession number of the method in a suitable controlled vocabulary (Crop Ontology, Trait Ontology).\n\n(DM-93) Scale accession number - Accession number of the scale in a suitable controlled vocabulary (Crop Ontology).", - "properties": { - "documentationLinks": { - "description": "links to various ontology documentation", - "items": { - "properties": { - "URL": { - "format": "uri", - "type": [ - "null", - "string" - ] - }, - "type": { - "enum": [ - "OBO", - "RDF", - "WEBPAGE", - null - ], - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "type": [ - "null", - "array" - ] - }, - "ontologyDbId": { - "description": "Ontology database unique identifier", - "type": "string" - }, - "ontologyName": { - "description": "Ontology name", - "type": "string" - }, - "version": { - "description": "Ontology version (no specific format)", - "type": [ - "null", - "string" - ] - } - }, - "required": [ - "ontologyName", - "ontologyDbId" - ], - "type": [ - "null", - "object" - ] + "$ref": "../BrAPI-Phenotyping/OntologyReference.json#/$defs/OntologyReference" }, "status": { "description": "Trait status (examples: \"recommended\", \"obsolete\", \"legacy\", etc.)", From c2b1e5f40091f205054e82ad4544c189f5057b7f Mon Sep 17 00:00:00 2001 From: Guy Davenport Date: Wed, 12 Jun 2024 17:37:32 +1200 Subject: [PATCH 9/9] publish on push to main --- .github/workflows/publish-package.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 9f8105d..3fa1eab 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -11,6 +11,9 @@ name: Publish package to the Maven Central Repository on: release: types: [created] + push: + branches: + - main workflow_dispatch: jobs: publish: